Haskell - 禁用伴随绑定检查haskell

时间:2016-10-30 10:21:09

标签: haskell ghc proof

我不想在Haskell中禁用检查伴随绑定的函数。

我想这样做的原因是能够通过矛盾来实现证明。以下类型签名没有任何绑定,因此不应该这样。

zeroDoesNotEqualOne :: Refl Z (S Z) -> Bottom

Refl Z (S Z)类型没有居民,因此不应该有任何约​​束力。

在上面的代码段中,类型意味着您的期望,S Z是Peano自然为1而Refl只有一个Refl a a

的居民

1 个答案:

答案 0 :(得分:3)

您不需要:使用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 Monin的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 ())