覆盖Haskell中的+

Hun*_*jos -1 constructor haskell types function matrix

我试图覆盖+符号,以学习如何定义自己的类型.我是Haskell的新手,我似乎无法克服这个错误.

这是我简单的新类型:

newtype Matrix x = Matrix x
(+):: (Num a, Num b, Num c) => Matrix [[a]] -> Matrix [[b]] -> Matrix [[c]]
x + y = Matrix zipWith (\ a b -> zipWith (+) a b) x y
Run Code Online (Sandbox Code Playgroud)

当我尝试将其加载到ghci时,我收到错误

linear_algebra.hs:9:42:
    Ambiguous occurrence ‘+’
    It could refer to either ‘Main.+’, defined at linear_algebra.hs:9:3
                          or ‘Prelude.+’,
                             imported from ‘Prelude’ at linear_algebra.hs:1:1
                             (and originally defined in ‘GHC.Num’)
Failed, modules loaded: none.
Run Code Online (Sandbox Code Playgroud)

用我的代码替换我的最后一行代码

x + y = Matrix zipWith (\ a b -> zipWith (Prelude.+) a b) x y
Run Code Online (Sandbox Code Playgroud)

给了我错误

    Couldn't match expected type ‘([Integer] -> [Integer] -> [Integer])
                                  -> Matrix [[a]] -> Matrix [[b]] -> Matrix [[c]]’
                with actual type ‘Matrix
                                    ((a0 -> b0 -> c0) -> [a0] -> [b0] -> [c0])’
    Relevant bindings include
      y :: Matrix [[b]] (bound at linear_algebra.hs:9:5)
      x :: Matrix [[a]] (bound at linear_algebra.hs:9:1)
      (+) :: Matrix [[a]] -> Matrix [[b]] -> Matrix [[c]]
        (bound at linear_algebra.hs:9:1)
    The function ‘Matrix’ is applied to four arguments,
    but its type ‘((a0 -> b0 -> c0) -> [a0] -> [b0] -> [c0])
                  -> Matrix ((a0 -> b0 -> c0) -> [a0] -> [b0] -> [c0])’
    has only one
    In the expression:
      Matrix zipWith (\ a b -> zipWith (Prelude.+) a b) x y
    In an equation for ‘+’:
        x + y = Matrix zipWith (\ a b -> zipWith (Prelude.+) a b) x y
Failed, modules loaded: none.
Run Code Online (Sandbox Code Playgroud)

能帮我理解错误是什么吗?我真的很感激.谢谢!

chi*_*chi 7

首先,类型

(+) :: (Num a, Num b, Num c) => Matrix [[a]] -> Matrix [[b]] -> Matrix [[c]]
Run Code Online (Sandbox Code Playgroud)

太笼统了.它声明您可以将任何数值矩阵与任何其他数值矩阵相加,即使元素类型不同,也可以生成第三种数字类型的矩阵(可能与前两种不同).也就是说,特别是浮点矩阵可以求和为双精度矩阵以产生整数矩阵.

你想要的

(+) :: Num a => Matrix [[a]] -> Matrix [[a]] -> Matrix [[a]]
Run Code Online (Sandbox Code Playgroud)

我建议在newtype中移动"list of list"类型

newtype Matrix a = Matrix [[a]]
Run Code Online (Sandbox Code Playgroud)

反映列表列表实现了这个Matrix概念.这给出了类型签名

(+) :: Num a => Matrix a -> Matrix a -> Matrix a
Run Code Online (Sandbox Code Playgroud)

要"覆盖" (+):Haskell中没有覆盖/重载.最接近的选项是:

  1. 定义模块本地函数(+).这将发生冲突Prelude.(+),因此+现在每个人都需要有资格消除歧义.我们不能写x + y,但我们需要x Prelude.+ yx MyModuleName.+ y.

  2. 为...实现一个Num实例Matrix a.这不是一个好主意,因为矩阵不是一个数字,但我们无论如何都可以尝试.

    instance Num a => Num (Matrix a) where
       Matrix xs + Matrix ys = Matrix (zipWith (zipWith (+)) xs ys)
       -- other Num operators here
      (*) = error "not implemented" -- We can't match dimension
      negate (Matrix xs) = Matrix (map (map negate) xs)
      abs = error "not implemented"
      signum = error "not implemented"
      fromInteger = error "not implemented"
    
    Run Code Online (Sandbox Code Playgroud)

    这与您的代码非常相似,缺少一些括号.并非所有其他方法都可以以完全有意义的方式实现,因为Num数字而不是矩阵.

  3. 使用不同的运算符,例如(^+)或其他