[英]Can GADTs be used to prove type inequalities in GHC?
因此,在我不斷嘗試通過小型Haskell練習半理解Curry-Howard時,我已經陷入了困境:
{-# LANGUAGE GADTs #-}
import Data.Void
type Not a = a -> Void
-- | The type of type equality proofs, which can only be instantiated if a = b.
data Equal a b where
Refl :: Equal a a
-- | Derive a contradiction from a putative proof of @Equal Int Char@.
intIsNotChar :: Not (Equal Int Char)
intIsNotChar intIsChar = ???
顯然, Equal Int Char
類型沒有(非底層)居民,因此在語義上應該有一個absurdEquality :: Equal Int Char -> a
函數......但對於我的生活我無法想出任何方式寫一個而不是使用undefined
。
所以要么:
我懷疑答案是這樣的:編譯器無法利用沒有沒有a = b的Equal
構造函數的事實。 但如果是這樣,那是什么讓它成真呢?
這是Philip JF解決方案的縮短版本,它是依賴類型理論家多年來一直反駁方程式的方式。
type family Discriminate x
type instance Discriminate Int = ()
type instance Discriminate Char = Void
transport :: Equal a b -> Discriminate a -> Discriminate b
transport Refl d = d
refute :: Equal Int Char -> Void
refute q = transport q ()
為了表明事物是不同的,你必須通過提供導致不同觀察的計算環境來捕捉它們表現不同的行為 。 Discriminate
提供了這樣一個上下文:一個類型級別的程序,它以不同的方式處理這兩種類型。
沒有必要求助於undefined
來解決這個問題。 總編程有時涉及拒絕不可能的輸入。 即使在undefined
的情況下,我也建議不要在總方法足夠的情況下使用它:總方法解釋了為什么某些東西是不可能的並且類型檢查者確認了; undefined
只記錄你的承諾 。 實際上,這種反駁方法是Epigram如何免除“不可能的案例”,同時確保案例分析涵蓋其領域。
至於計算行為,請注意,通過transport
refute
在q
必然是嚴格的,並且q
在空上下文中不能計算為正常形式,因為不存在這樣的頭部正規形式(並且因為計算保留類型,當然)。 在完整設置中,我們確信在運行時永遠不會調用refute
。 在Haskell中,我們至少可以肯定,在我們不得不對它做出回應之前,它的論點會分歧或拋出異常。 一個懶惰的版本,如
absurdEquality e = error "you have a type error likely to cause big problems"
將忽略e
的毒性並告訴您,如果不這樣做,則會出現類型錯誤。 我更喜歡
absurdEquality e = e `seq` error "sue me if this happens"
如果誠實的反駁太過於艱苦的工作。
我不明白使用undefined
的問題每個類型都在Haskell的底部居住。 我們的語言沒有強烈正常化......你正在尋找錯誤的東西。 Equal Int Char
導致類型錯誤不是很好保存異常。 看到
{-# LANGUAGE GADTs, TypeFamilies #-}
data Equal a b where
Refl :: Equal a a
type family Pick cond a b
type instance Pick Char a b = a
type instance Pick Int a b = b
newtype Picker cond a b = Picker (Pick cond a b)
pick :: b -> Picker Int a b
pick = Picker
unpick :: Picker Char a b -> a
unpick (Picker x) = x
samePicker :: Equal t1 t2 -> Picker t1 a b -> Picker t2 a b
samePicker Refl x = x
absurdCoerce :: Equal Int Char -> a -> b
absurdCoerce e x = unpick (samePicker e (pick x))
你可以用它來創建你想要的功能
absurdEquality e = absurdCoerce e ()
但這將產生未定義的行為作為其計算規則。 false
應該導致程序中止,或者至少可以運行。 中止是一種計算規則,類似於通過添加not而將最小邏輯轉換為語言邏輯。 正確的定義是
absurdEquality e = error "you have a type error likely to cause big problems"
關於標題中的問題:基本上沒有。 據我所知,在當前的Haskell中,類型不等式在實際方面是不可表示的。 類型系統的改變可能導致這種情況越來越好,但截至目前,我們有平等但不平等。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.