你並不需要:使用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 {}
既然你都在談論定理的評論證明它讓我的思想和事實證明,我們可以玩一個小遊戲勒柯克用戶喜歡頗有幾分:使用類型級別的對角線函數。參看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())
我試過了,但隨後又跟隨編譯:'zeroNeqOne :: Z ==ž - >了',它不該」 t(像'ghci ZeroNeqOne.hs -XDataKinds -fwarn-incomplete-patterns -Werror'編譯)。 –
它似乎是[覆蓋檢查器中的錯誤](https://ghc.haskell.org/trac/ghc/ticket/10746)。所以現在你在使用空箱時需要小心。這就是說,它沒有像你要求的那樣沒有伴隨定義的類型簽名更危險。 – gallais
希望是我可以在沒有附加綁定的情況下實現這一點,並且在存在模式時也會出現編譯時錯誤。無論如何,我認爲realt理論證明了當做嚴肅的事情時首選。但是,謝謝! –