[英]Why we cannot pattern match on Set/Type in Coq/Agda/Idris?
考慮一個接受Set的函數,並返回其字節長度,名為byteLength
:
byteLength : Set -> Maybe Nat
如果我想直接實現這個函數,我需要在類型參數上進行模式匹配:
byteLength Char = Just 1
byteLength Double = Just 8
byteLength _ = Nothing
但由於不允許在Set / Type上進行模式匹配,因此上述代碼無法編譯。
所以我們必須將接口定義為變通方法
Interface ByteLength a where
byteLength : Nat
implement ByteLength Char where
byteLength = 1
並且以更一般的方式,也許我們可以使用TypeRep之類的東西在TypeRep上執行類似的事情和模式匹配。 但TypeRep也被定義為接口。
我認為使用Interface和使用forall是非常不同的,因為Interface意味着“對於某些類型”,而forall意味着“適用於所有類型”。
我想知道為什么這些DT語言不支持Set / Type上的模式匹配,是否有一些我不知道的特殊原因?
在Agda,Idris,Haskell和許多其他語言中,對類型的量化是參數化的 (與允許在類型上匹配的ad-hoc多態相反)。 從實現的角度來看,這意味着編譯器可以從程序中擦除所有類型,因為函數永遠不會在計算上依賴於類型Set
的參數。 能夠擦除類型在依賴類型語言中尤其重要,因為類型通常可以成為巨大的表達。
從更理論的角度來看,參數多態是很好的,因為它允許我們通過查看它的類型來推斷函數的某些屬性, 由Phil Wadler雄辯地描述為“自由定理” 。 我可以嘗試給你這篇論文的要點,但你應該真的去看看它。
當然,有時需要ad-hoc多態來實現一個函數,這就是Haskell和Idris有類型類的原因 (Agda有一個類似的特性叫做實例參數 ,而Coq有規范結構和類型類)。 例如,在Agda中,您可以定義如下記錄:
record ByteLength (A : Set) : Set where
field
theByteLength : Nat
open ByteLength
byteLength : (A : Set) {{_ : ByteLength A}} -> Nat
byteLength A {{bl}} = bl .theByteLength
然后你可以通過定義實例為各種類型定義byteLength函數:
instance
byteLengthChar : ByteLength Char
byteLengthChar .theByteLength = 1
byteLengthDouble : ByteLength Double
byteLengthDouble .theByteLength = 8
使用此代碼, byteLength Char
計算結果為1
而byteLength Double
計算結果為8
,而它會引發任何其他類型的類型錯誤。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.