[英]Pattern Matching on GADTs
我為表達式創建了一個GADT。 當我對具有約束的構造函數進行模式匹配時,類型檢查器無法推斷出對構造函數約束中使用的類型變量的約束。 我認為代碼和錯誤信息更具說明性。
{-# LANGUAGE GADTs, MultiParamTypeClasses #-}
import Data.Word
data Expr a where
Value :: a -> Expr a
Cast :: (Castable a b) => Expr a -> Expr b
class Castable a b where
cast :: a -> b
instance Castable Word64 Word32 where
cast = fromIntegral
instance (Show a) => Show (Expr a) where
show (Cast e) = "Cast " ++ show e -- ERROR
我得到的錯誤:
gadt.hs:16:30:
Could not deduce (Show a1) arising from a use of `show'
from the context (Show a)
bound by the instance declaration at gadt.hs:15:10-34
or from (Castable a1 a)
bound by a pattern with constructor
Cast :: forall b a. Castable a b => Expr a -> Expr b,
in an equation for `show'
at gadt.hs:16:9-14
Possible fix:
add (Show a1) to the context of
the data constructor `Cast'
or the instance declaration
In the second argument of `(++)', namely `show e'
In the expression: "Cast " ++ show e
In an equation for `show': show (Cast e) = "Cast " ++ show e
編輯:如果我注釋掉Show (Expr a)
實例並添加以下代碼,它可以正常工作:
eval :: Expr a -> a
eval (Value a) = a
eval (Cast e) = cast $ eval e
main = do
let bigvalue = maxBound `div` 2 + 5 :: Word64
e = Cast (Value bigvalue) :: Expr Word32
v = eval e
putStrLn "typechecks."
print (bigvalue, v)
我希望show實例基本上打印類似Cast (Value bigvalue)
東西。
Cast :: (Castable a b) => Expr a -> Expr b
所以在這里:
instance (Show a) => Show (Expr a) where
show (Cast e) = "Cast " ++ show e -- ERROR
Cast e
的類型為Expr a
。 我們有一個Show a
約束,並且這個實例暗示了Show (Expr a)
,所以我們可以在Expr a
類型的東西上調用show
。
但是e
不是 Expr a
類型Expr a
。 Cast
接受任何類型Expr a1
的參數,並為您提供Expr a
(重命名類型變量以保持與我們在實例中討論的內容一致),因此e
的類型為Expr a1
。 我們沒有類型a1
的Show
約束,我們要求Show a1
暗示Show (Expr a1)
,所以沒有辦法show e
。
並且無法在Show
實例中添加這樣的約束,因為類型a1
不會出現在Cast e
的類型中。 這似乎是在這里使用GADT的重點; 你故意扔掉有關Cast
應用的東西類型的所有信息(除了Castable a1 a
保存的事實),並宣布結果只是Expr a
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.