GADT を検討する
data S a where
S :: Show a => S a
そしてコードの実行
foo :: S a -> a -> String
foo s x = case s of
S -> show x
ディクショナリベースの Haskell 実装では、値s
がクラス ディクショナリを保持していて、実行できるようにそのディクショナリから関数をcase
抽出することが期待されます。show
show x
実行すると
foo undefined (\x::Int -> 4::Int)
例外があります。ディクショナリにアクセスできないため、操作上、これは予想されます。より一般的には、 ( ではない場合)case (undefined :: T) of K -> ...
の評価を強制するため、エラーが発生します。undefined
T
newtype
コードを考えてみましょう (これがコンパイルされるとしましょう)
bar :: S a -> a -> String
bar s x = let S = s in show x
との実行
bar undefined (\x::Int -> 4::Int)
これは何をすべきですか?と同じ例外を生成する必要があると主張する人もいるかもしれませんfoo
。この場合、参照透過性は次のことを意味します。
let S = undefined :: S (Int->Int) in show (\x::Int -> 4::Int)
同じ例外で失敗します。これは、が式let
を評価していることを意味しundefined
ます。たとえば、非常に異なります。
let [] = undefined :: [Int] in 5
に評価され5
ます。
実際、 a のパターンlet
は遅延型です: とは異なり、式の評価を強制しませんcase
。これが理由です。
let (x,y) = undefined :: (Int,Char) in 5
に正常に評価され5
ます。
でaが必要かどうかをlet S = e in e'
評価させたいと思うかもしれませんが、それはかなり奇妙に感じます。また、評価するとき、 、、または両方を評価するかどうかが不明確になります。e
show
e'
let S = e1 ; S = e2 in show ...
e1
e2
GHC は現在、単純な規則でこれらすべてのケースを禁止することを選択しています: GADT を削除するときに怠惰なパターンはありません。