[英]return type of GADT evaluator
I'm a bit at a loss as to why the last pattern in prodV in the following doesn't work: 我对为什么以下prodV中的最后一个模式不起作用感到有些困惑:
{-# LANGUAGE GADTs #-}
data V a where
V0 :: Float -> V Float
Vn :: [Float] -> V [Float]
prodV :: (Num a) => V a -> V a -> a
prodV (V0 x) (V0 y) = x * y
-- prodV (Vn x) (Vn y) = zipWith (*) x y -- this one works
prodV (Vn xs) (Vn ys) = [ sum $ zipWith (*) xs ys ]
prodV (V0 n) (Vn ys) = map (* n) ys
GHCi 7.8.3 complains: GHCi 7.8.3抱怨:
Couldn't match type ‘Float’ with ‘[Float]’
Inaccessible code in
a pattern with constructor
Vn :: [Float] -> V [Float],
in an equation for ‘prodV’
In the pattern: Vn ys`
Any pointers? 有指针吗? thanks in advance
提前致谢
Well, GHC tells you exactly what the problem is. 好吧,GHC会告诉您确切的问题所在。 From your definition,
V0 something
always has the type V Float
(and something
should be of type Float
— but that's not relevant here), while Vn anything
always has the type V [Float]
. 根据您的定义,
V0 something
始终为V Float
类型( something
应为Float
类型-但这与此处无关),而Vn anything
始终为V [Float]
类型。 But the type signature for prodV
specifies that both have the same type V a
. 但是
prodV
的类型签名指定两者都具有相同的V a
。 So, in this case a
should be Float
and [Float]
at the same time, which is impossible. 因此,在这种情况下,
a
应该同时为Float
和[Float]
,这是不可能的。
The signature 签名
prodV :: (Num a) => V a -> V a -> a
mandates that both arguments have the same type parameter, but if you match on V0
and Vn
the arguments would have to have the types V Float
and V [Float]
in which the type parameter does not match. 强制两个参数具有相同的类型参数,但是如果在
V0
和Vn
上匹配,则参数将必须具有类型参数不匹配的类型V Float
和V [Float]
。
I'm not quite sure what you want the semantics to be but I'm guessing that you want to define the GADT as something like 我不太确定您想要的语义是什么,但是我猜您想将GADT定义为类似
data V n where
V0 :: n -> V n
Vn :: [n] -> V n
and your function as either 和你的功能
prodV :: (Num a) => V a -> V a -> V a
prodV (V0 x) (V0 y) = V0 $ x * y
prodV (Vn xs) (Vn ys) = Vn $ zipWith (*) xs ys
prodV (V0 n) (Vn ys) = Vn $ map (* n) ys
or possibly 或可能
prodV' :: (Num a) => V a -> V a -> a
prodV' (V0 x) (V0 y) = x * y
prodV' (Vn xs) (Vn ys) = sum $ zipWith (*) xs ys
prodV' (V0 n) (Vn ys) = sum $ map (* n) ys
Can you describe what you would like the function prodV
to actually do? 您能描述一下您希望函数
prodV
实际执行的操作吗? The types in your original code don't really make sense to me as they are. 原始代码中的类型对我来说真的没有意义。
I was just trying to understand how to overload functions in order to mimic algebraic shorthand, but I guess this isn't the right avenue. 我只是想了解如何重载函数以模仿代数速记,但我想这不是正确的途径。 What would the idiomatic Haskell way to do this?
Haskell的惯用方式是什么? Eg from Numeric.Matrix :
例如,来自Numeric.Matrix :
adaptScalar f1 f2 f3 x y
| dim x == 1 = f1 (x@>0) y
| dim y == 1 = f3 x (y@>0)
| otherwise = f2 x y
instance Num (Vector Float) where
(+) = adaptScalar addConstant add (flip addConstant)
negate = scale (-1)
(*) = adaptScalar scale mul (flip scale)
signum = vectorMapF Sign
abs = vectorMapF Abs
fromInteger = fromList . return . fromInteger
picks the right implementation of the operator (eg + or *) according to the dimension of the operands. 根据操作数的维数选择运算符的正确实现(例如+或*)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.