使用类型约束时无法推断错误

sda*_*das 1 haskell linear-algebra

我正在使用Haskell来实现线性代数示例.但是,我在声明magnitude函数时遇到了问题.

我的实现如下:

magnitude :: (Foldable t, Functor t, Floating a) => t a -> a
magnitude = sqrt $ Data.Foldable.foldr1 (+) $ fmap (^2)
Run Code Online (Sandbox Code Playgroud)

这个想法是magnitude接受Vec2D,Vec3D或者Vec4D,并返回其组件的平方和的平方根.

三种矢量类型中的每一种都实现FunctorFoldable.例如,

newtype Vec2D = Vec2D (a, a) deriving (Eq, Show)
instance Functor Vec2D where
    fmap f (Vec2D (x, y)) = Vec2D (f x, f y)
instance Foldable Vec2D where
    foldr f b (Vec2D (x, y)) = f x $ f y b
Run Code Online (Sandbox Code Playgroud)

但是,我收到了很多错误:

LinearAlgebra.hs:9:13:
    Could not deduce (Floating (t a -> a)) arising from a use of `sqrt'
    from the context (Foldable t, Functor t, Floating a)
      bound by the type signature for
                 magnitude :: (Foldable t, Functor t, Floating a) => t a -> a
      at LinearAlgebra.hs:8:14-60
    Possible fix: add an instance declaration for (Floating (t a -> a))
    In the expression: sqrt
    In the expression: sqrt $ Data.Foldable.foldr1 (+) $ fmap (^ 2)
    In an equation for `magnitude':
        magnitude = sqrt $ Data.Foldable.foldr1 (+) $ fmap (^ 2)

LinearAlgebra.hs:9:20:
    Could not deduce (Foldable ((->) (t a -> a)))
      arising from a use of `Data.Foldable.foldr1'
    from the context (Foldable t, Functor t, Floating a)
      bound by the type signature for
                 magnitude :: (Foldable t, Functor t, Floating a) => t a -> a
      at LinearAlgebra.hs:8:14-60
    Possible fix:
      add an instance declaration for (Foldable ((->) (t a -> a)))
    In the expression: Data.Foldable.foldr1 (+)
    In the second argument of `($)', namely
      `Data.Foldable.foldr1 (+) $ fmap (^ 2)'
    In the expression: sqrt $ Data.Foldable.foldr1 (+) $ fmap (^ 2)

LinearAlgebra.hs:9:41:
    Could not deduce (Num (t a -> a)) arising from a use of `+'
    from the context (Foldable t, Functor t, Floating a)
      bound by the type signature for
                 magnitude :: (Foldable t, Functor t, Floating a) => t a -> a
      at LinearAlgebra.hs:8:14-60
    Possible fix: add an instance declaration for (Num (t a -> a))
    In the first argument of `Data.Foldable.foldr1', namely `(+)'
    In the expression: Data.Foldable.foldr1 (+)
    In the second argument of `($)', namely
      `Data.Foldable.foldr1 (+) $ fmap (^ 2)'
Failed, modules loaded: none.
Run Code Online (Sandbox Code Playgroud)

我并不完全舒服Functor或者Foldable还没有-我认为这是错误的间接原因.

有人可以向我解释错误消息指向的是什么吗?

J. *_*son 5

您应该将您的功能组合到一个(.)没有的管道中($).发生此错误的原因是,例如,Data.Foldable.foldr1 (+)期望将其应用于Foldable类似的类型,[a]但实际上您将其直接应用于fmap (^2)函数.

magnitude :: (Foldable t, Functor t, Floating a) => t a -> a
magnitude = sqrt . Data.Foldable.foldr1 (+) . fmap (^2)
Run Code Online (Sandbox Code Playgroud)

要么

magnitude :: (Foldable t, Functor t, Floating a) => t a -> a
magnitude ta = sqrt $ Data.Foldable.foldr1 (+) $ fmap (^2) $ ta
Run Code Online (Sandbox Code Playgroud)

两者都会做得更好.