如何获得与向量一起使用的通用平均值以在 Haskell 中编译?
How to get a generic average that works with vectors to compile in Haskell?
我试过了:
import Data.VectorSpace -- ^/
import Data.AdditiveGroup -- sumV
import Data.Foldable -- length
avg :: (Foldable f, VectorSpace a) => f a -> a
avg xs = sm ^/ sz -- could be just ^*(1/sz)
where sm = sumV xs
sz = fromIntegral (length xs)
并得到:
Distancesumcurves.hs:11:10: error:
• Could not deduce (Fractional (Scalar a))
arising from a use of ‘^/’
from the context: (Foldable f, VectorSpace a)
bound by the type signature for:
avg :: (Foldable f, VectorSpace a) => f a -> a
at Distancesumcurves.hs:10:1-46
• In the expression: sm ^/ sz
In an equation for ‘avg’:
avg xs
= sm ^/ sz
where
sm = sumV xs
sz = fromIntegral (length xs)
Distancesumcurves.hs:13:13: error:
• Could not deduce (Num (Scalar a))
arising from a use of ‘fromIntegral’
from the context: (Foldable f, VectorSpace a)
bound by the type signature for:
avg :: (Foldable f, VectorSpace a) => f a -> a
at Distancesumcurves.hs:10:1-46
• In the expression: fromIntegral (length xs)
In an equation for ‘sz’: sz = fromIntegral (length xs)
In an equation for ‘avg’:
avg xs
= sm ^/ sz
where
sm = sumV xs
sz = fromIntegral (length xs)
当然我可以专门为向量写一个,然后继续我的生活,但是 Haskell 的通用特性有什么意义呢?用一种不那么迂腐的语言我已经完成了它,它会工作得很好,而且它是可重用的。在 Haskell 我必须在这里写一个问题或回归到代码重复。我认为这是语言的失败。
这不是我第一次对 Haskell 泛型感到沮丧。我已经超过了 Graham Hutton 在 Haskell 中编程一书的水平。对我来说,下一个 step/book/article 应该是什么?这样当我知道我想要什么并且它是正确的时,我就不会与编译器争论。在这种情况下,我缺乏的只是语言技术技能。如果我错了,请随时纠正我。
编辑:
似乎在上下文中有效
approximateCurve :: [Point] -> Path
approximateCurve pts = [] -- TODO
where center = avg pts
avg vs = (sum vs) ^/ (fromIntegral (length vs))
sum = foldr (^+^) (0,0)
在这种情况下,我会添加错误消息中建议的附加约束,以获得 avg :: (Foldable f, VectorSpace a, Fractional (Scalar a)) => f a -> a
。
Fractional
表示Num
,不用说Num
。如果你添加它也没有坏处 - 该功能并没有变得不那么通用。
就一般建议而言,我认为在类型错误的指导下编写大量泛型函数是最好的方法。通常添加建议的约束就足够了;其他时候你真的想要更通用的签名,并且需要弄清楚哪个函数带来了不需要的约束。
我试过了:
import Data.VectorSpace -- ^/
import Data.AdditiveGroup -- sumV
import Data.Foldable -- length
avg :: (Foldable f, VectorSpace a) => f a -> a
avg xs = sm ^/ sz -- could be just ^*(1/sz)
where sm = sumV xs
sz = fromIntegral (length xs)
并得到:
Distancesumcurves.hs:11:10: error:
• Could not deduce (Fractional (Scalar a))
arising from a use of ‘^/’
from the context: (Foldable f, VectorSpace a)
bound by the type signature for:
avg :: (Foldable f, VectorSpace a) => f a -> a
at Distancesumcurves.hs:10:1-46
• In the expression: sm ^/ sz
In an equation for ‘avg’:
avg xs
= sm ^/ sz
where
sm = sumV xs
sz = fromIntegral (length xs)
Distancesumcurves.hs:13:13: error:
• Could not deduce (Num (Scalar a))
arising from a use of ‘fromIntegral’
from the context: (Foldable f, VectorSpace a)
bound by the type signature for:
avg :: (Foldable f, VectorSpace a) => f a -> a
at Distancesumcurves.hs:10:1-46
• In the expression: fromIntegral (length xs)
In an equation for ‘sz’: sz = fromIntegral (length xs)
In an equation for ‘avg’:
avg xs
= sm ^/ sz
where
sm = sumV xs
sz = fromIntegral (length xs)
当然我可以专门为向量写一个,然后继续我的生活,但是 Haskell 的通用特性有什么意义呢?用一种不那么迂腐的语言我已经完成了它,它会工作得很好,而且它是可重用的。在 Haskell 我必须在这里写一个问题或回归到代码重复。我认为这是语言的失败。
这不是我第一次对 Haskell 泛型感到沮丧。我已经超过了 Graham Hutton 在 Haskell 中编程一书的水平。对我来说,下一个 step/book/article 应该是什么?这样当我知道我想要什么并且它是正确的时,我就不会与编译器争论。在这种情况下,我缺乏的只是语言技术技能。如果我错了,请随时纠正我。
编辑:
似乎在上下文中有效
approximateCurve :: [Point] -> Path
approximateCurve pts = [] -- TODO
where center = avg pts
avg vs = (sum vs) ^/ (fromIntegral (length vs))
sum = foldr (^+^) (0,0)
在这种情况下,我会添加错误消息中建议的附加约束,以获得 avg :: (Foldable f, VectorSpace a, Fractional (Scalar a)) => f a -> a
。
Fractional
表示Num
,不用说Num
。如果你添加它也没有坏处 - 该功能并没有变得不那么通用。
就一般建议而言,我认为在类型错误的指导下编写大量泛型函数是最好的方法。通常添加建议的约束就足够了;其他时候你真的想要更通用的签名,并且需要弄清楚哪个函数带来了不需要的约束。