Haskell - 禁用伴随绑定检查 haskell
Haskell - disable accompanying binding check haskell
我不想在 Haskell 中禁用检查伴随绑定的功能。
我想这样做的原因是能够实现反证法。以下类型签名没有任何绑定,也不应该有。
zeroDoesNotEqualOne :: Refl Z (S Z) -> Bottom
类型 Refl Z (S Z)
没有居民,因此应该没有绑定。
在上面的代码片段中,类型表示您所期望的类型,例如 S Z
是 1 的 Peano 自然数,而 Refl
只有一个 Refl a a
[=17 类型的居民=]
你不需要:使用EmptyCase
语言扩展,这个陈述实际上是可以证明的。这是一个演示它的独立文件:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE EmptyCase #-}
module ZeroNeqOne where
data (==) a b where
Refl :: a == a
data Nat where
Z :: Nat
S :: Nat -> Nat
zeroNeqOne :: Z == S Z -> a
zeroNeqOne p = case p of {}
鉴于你在评论中谈论定理证明,这让我开始思考,结果证明我们可以玩一个 Coq 用户非常喜欢的小游戏:在类型级别使用对角线函数。比照。 JF 莫宁 Proof Trick: Small inversions。这次我们将使用 TypeFamilies
扩展名。丢弃矛盾的 a == b
的想法是使用一个类型级函数,它会要求我们在 a
出现时证明一个微不足道的目标,而在 b
出现时要求我们证明一个不可能的目标。然后使用相等性证明将平凡的结果传输到不可能的结果:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
module ZeroNeqOneDiag where
import Data.Void
data (==) a b where
Refl :: a == a
subst :: a == b -> p a -> p b
subst Refl pa = pa
data Nat where
Z :: Nat
S :: Nat -> Nat
type family Diag (n :: Nat) :: * where
Diag 'Z = ()
Diag ('S n) = Void
newtype Diagonal n = Diagonal { runDiagonal :: Diag n }
zeroNeqOneDiag :: 'Z == 'S 'Z -> Void
zeroNeqOneDiag p = runDiagonal $ subst p (Diagonal ())
我不想在 Haskell 中禁用检查伴随绑定的功能。
我想这样做的原因是能够实现反证法。以下类型签名没有任何绑定,也不应该有。
zeroDoesNotEqualOne :: Refl Z (S Z) -> Bottom
类型 Refl Z (S Z)
没有居民,因此应该没有绑定。
在上面的代码片段中,类型表示您所期望的类型,例如 S Z
是 1 的 Peano 自然数,而 Refl
只有一个 Refl a a
[=17 类型的居民=]
你不需要:使用EmptyCase
语言扩展,这个陈述实际上是可以证明的。这是一个演示它的独立文件:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE EmptyCase #-}
module ZeroNeqOne where
data (==) a b where
Refl :: a == a
data Nat where
Z :: Nat
S :: Nat -> Nat
zeroNeqOne :: Z == S Z -> a
zeroNeqOne p = case p of {}
鉴于你在评论中谈论定理证明,这让我开始思考,结果证明我们可以玩一个 Coq 用户非常喜欢的小游戏:在类型级别使用对角线函数。比照。 JF 莫宁 Proof Trick: Small inversions。这次我们将使用 TypeFamilies
扩展名。丢弃矛盾的 a == b
的想法是使用一个类型级函数,它会要求我们在 a
出现时证明一个微不足道的目标,而在 b
出现时要求我们证明一个不可能的目标。然后使用相等性证明将平凡的结果传输到不可能的结果:
{-# LANGUAGE GADTs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
module ZeroNeqOneDiag where
import Data.Void
data (==) a b where
Refl :: a == a
subst :: a == b -> p a -> p b
subst Refl pa = pa
data Nat where
Z :: Nat
S :: Nat -> Nat
type family Diag (n :: Nat) :: * where
Diag 'Z = ()
Diag ('S n) = Void
newtype Diagonal n = Diagonal { runDiagonal :: Diag n }
zeroNeqOneDiag :: 'Z == 'S 'Z -> Void
zeroNeqOneDiag p = runDiagonal $ subst p (Diagonal ())