簡體   English   中英

GADT可以用來證明GHC中的類型不等式嗎?

[英]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

所以要么:

  1. 我錯過了什么,或者
  2. 這種語言存在一些限制,這使得這項任務變得不可能,而且我還沒有理解它是什么。

我懷疑答案是這樣的:編譯器無法利用沒有沒有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 refuteq必然是嚴格的,並且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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM