【发布时间】:2016-04-07 17:17:38
【问题描述】:
我想知道是否可以编写一个 Haskell 加法运算符来处理两个数字、两个数字列表、两个数字矩阵……等等。也就是说,是否可以定义一个<+> 以使以下所有工作都有效?:
1 <+> 2 = 3
[1] <+> [2] = [3]
[[1]] <+> [[2]] = [[3]]
...
我知道就像What is an idiomatic way to add lists in Haskell? 一样,我们可以为a 做+,为zipWith (+) 做[a]。 [[a]] 可能是 zipWith (zipWith (+)),沿着同一条线,依此类推……
但它可以使用一个运算符(就像 Matlab 一样)使用类型类或 Haskell 的其他功能来完成吗?
我知道这是合成糖,但如果可能的话它会很甜。
-- 更新--
我发现使用(Num a) 可能会出现问题,正如@DanielWagner 的回答中所解释的那样,对于基本情况,最好为Integer, Double 等单独定义它。
为了记录,我只是按照建议尝试了:
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
class Additive a where (<+>) :: a -> a -> a
instance Num a => Additive a where (<+>) = (+)
instance Additive a => Additive [a] where (<+>) = zipWith (<+>)
或者
{-# LANGUAGE DefaultSignatures #-}
class Additive a where
(<+>) :: a -> a -> a
default (<+>) :: Num a => a -> a -> a
(<+>) = (+)
在任何一种情况下,加载.hs 文件或评估[[1,2]] <+> [[3,4]] 时都会出错。
【问题讨论】:
-
好吧,你可以编写一个类似
Monoid的类,但有不同的实例。 -
为了让这个有趣,您需要提供更详尽的示例。你想要
[1,2] <+> [3,4]给什么?[[1,2],[3,4]] <+> [[5,6],[7,8]]呢?[1,2,3,4] <+> []呢?有很多边缘情况需要考虑。 -
Matlab/Octave 在最后一个例子中会给出尺寸不匹配错误,否则它是一个
X(i,j) + Y(i,j)。 -
即使有可能,这也是个坏主意。如果你问我,Matlab 实际上已经很好地证明了这一点......
-
@leftaroundabout 我认为这对 Matlab 来说是个坏主意,因为尺寸被任意折叠以允许例如1 + [2]。这里不是这样吗?