首页 > 解决方案 > 如何获得与向量一起使用的通用平均值以在 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 编程》一书的水平。对我来说下一步/书/文章应该是什么?这样当我知道我想要什么并且它是正确的时,我就不会与编译器争论。在这种情况下,我缺乏的只是语言技术技能。如果我错了,请随时纠正我。


编辑:

似乎在上下文中工作

approximateCurve :: [Point] -> Path
approximateCurve pts = [] -- TODO
 where center = avg pts
       avg vs = (sum vs) ^/ (fromIntegral (length vs))
       sum = foldr (^+^) (0,0)

标签: haskellgenericstypesnumbersgeneric-programming

解决方案


在这种情况下,我将添加错误消息中建议的附加约束,以获取avg :: (Foldable f, VectorSpace a, Fractional (Scalar a)) => f a -> a.

Fractional暗示Num,所以无需赘述Num。如果你添加它也没有什么坏处——这个功能并没有变得不那么通用。

就一般建议而言,我认为在类型错误的指导下编写大量通用函数是最好的方法。通常添加建议的约束就足够了;其他时候你真的想要更通用的签名,并且需要找出哪个函数带来了不需要的约束。


推荐阅读