![](/img/trans.png)
[英]Haskell GADT typesafe Evaluator: Constant term for more than one type.
[英]return type of GADT evaluator
我对为什么以下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抱怨:
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`
有指针吗? 提前致谢
好吧,GHC会告诉您确切的问题所在。 根据您的定义, V0 something
始终为V Float
类型( something
应为Float
类型-但这与此处无关),而Vn anything
始终为V [Float]
类型。 但是prodV
的类型签名指定两者都具有相同的V a
。 因此,在这种情况下, a
应该同时为Float
和[Float]
,这是不可能的。
签名
prodV :: (Num a) => V a -> V a -> a
强制两个参数具有相同的类型参数,但是如果在V0
和Vn
上匹配,则参数将必须具有类型参数不匹配的类型V Float
和V [Float]
。
我不太确定您想要的语义是什么,但是我猜您想将GADT定义为类似
data V n where
V0 :: n -> V n
Vn :: [n] -> V n
和你的功能
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
或可能
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
您能描述一下您希望函数prodV
实际执行的操作吗? 原始代码中的类型对我来说真的没有意义。
我只是想了解如何重载函数以模仿代数速记,但我想这不是正确的途径。 Haskell的惯用方式是什么? 例如,来自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
根据操作数的维数选择运算符的正确实现(例如+或*)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.