简体   繁体   English

GADT评估程序的返回类型

[英]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. 强制两个参数具有相同的类型参数,但是如果在V0Vn上匹配,则参数将必须具有类型参数不匹配的类型V FloatV [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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM