2016-01-04 29 views
3

我想知道是否可以编写一个可以在两个数字,两个数字列表,两个数字矩阵等等上工作的Haskell添加运算符。也就是说,是否有可能定义一个<+>,使得所有的下列作品?:如何在Haskell中添加两个类似matlab的列表?

1 <+> 2 = 3 
[1] <+> [2] = [3] 
[[1]] <+> [[2]] = [[3]] 
... 

我知道,在What is an idiomatic way to add lists in Haskell?,我们可以为a+zipWith (+)[a]。可能zipWith (zipWith (+))[[a]],沿着同一行,依此类推......

但它可以使用一个运算符(因为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]]时,当有错误。

+5

那么,你可以写一个非常类似于'Monoid'的类,它有不同的实例。 – dfeuer

+3

为了使这个有趣,你需要提供更完整的例子。你想要什么?[1,2] <+> [3,4]'给?那么'[[1,2],[3,4]] <+> [[5,6],[7,8]]'?那么'[1,2,3,4] <+> []'?有很多边缘案例需要考虑。 –

+1

Matlab/Octave会在上一个例子中给出尺寸不匹配的错误,否则它是'X(i,j)+ Y(i,j)'。 –

回答

5

是的,这是可能的:

class Additive a where (<+>) :: a -> a -> a 
instance Additive Integer where (<+>) = (+) 
instance Additive a => Additive [a] where (<+>) = zipWith (<+>) 

你三个测试用例在ghci的:

*Main> 1 <+> 2 
3 
*Main> [1] <+> [2] 
[3] 
*Main> [[1]] <+> [[2]] 
[[3]] 

如果你想大量的实例,其中(<+>) = (+),可以使这个缺省实现DefaultSignatures

{-# LANGUAGE DefaultSignatures #-} 
class Additive a where 
    (<+>) :: a -> a -> a 
    default (<+>) :: Num a => a -> a -> a 
    (<+>) = (+) 

优点是,一些inst王牌可能很短,例如

instance Additive Integer 
instance Additive Int 
instance Additive Double 
instance Additive Float 

将全部按预期工作,没有任何附加的方法定义。

+0

任何优雅的方式来取代'整数'与'NUM'? –

+0

当然:'实例Num a =>添加剂a其中(<+>)=(+)' –

+0

@ReinHenrichs仅适用于'FlexibleInstances'右侧的作用? –