[英]Pattern Matching on GADTs
I've created a GADT for expressions. 我为表达式创建了一个GADT。 When I pattern match on constructors that have constraints, the typechecker is unable to deduce constraints on the type variables used in the constructor's constraints.
当我对具有约束的构造函数进行模式匹配时,类型检查器无法推断出对构造函数约束中使用的类型变量的约束。 I think the code and error message are more elucidating.
我认为代码和错误信息更具说明性。
{-# 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
The error I get: 我得到的错误:
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
Edit: If I comment out the Show (Expr a)
instance and add the following code, it works fine: 编辑:如果我注释掉
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)
I would want the show instance to basically print something like Cast (Value bigvalue)
. 我希望show实例基本上打印类似
Cast (Value bigvalue)
东西。
Cast :: (Castable a b) => Expr a -> Expr b
So here: 所以在这里:
instance (Show a) => Show (Expr a) where
show (Cast e) = "Cast " ++ show e -- ERROR
Cast e
is of type Expr a
. Cast e
的类型为Expr a
。 We have a Show a
constraint, and by this very instance that implies Show (Expr a)
, so we can call show
on things of type Expr a
. 我们有一个
Show a
约束,并且这个实例暗示了Show (Expr a)
,所以我们可以在Expr a
类型的东西上调用show
。
But e
is not of type Expr a
. 但是
e
不是 Expr a
类型Expr a
。 Cast
takes an argument of any type Expr a1
and gives you an Expr a
(renaming the type variables to stay consistent with what we're talking about in the instance), so e
is of type Expr a1
. Cast
接受任何类型Expr a1
的参数,并为您提供Expr a
(重命名类型变量以保持与我们在实例中讨论的内容一致),因此e
的类型为Expr a1
。 We don't have a Show
constraint for the type a1
, and we require Show a1
to imply Show (Expr a1)
, so there's no way to show e
. 我们没有类型
a1
的Show
约束,我们要求Show a1
暗示Show (Expr a1)
,所以没有办法show e
。
And there's no way to add such a constraint in the Show
instance, because the type a1
doesn't appear in the type of Cast e
. 并且无法在
Show
实例中添加这样的约束,因为类型a1
不会出现在Cast e
的类型中。 That seems to be the whole point of using a GADT here; 这似乎是在这里使用GADT的重点; you've deliberately thrown away all information about the type of the thing that
Cast
was applied to (other than the fact that Castable a1 a
holds), and declared the result to simply be Expr a
. 你故意扔掉有关
Cast
应用的东西类型的所有信息(除了Castable a1 a
保存的事实),并宣布结果只是Expr a
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.