0

我有以下类型定义:

data NumList n = NumList [Rational]

然后在我的代码中我定义了一些像这样的数字列表,

n1 = NumList [1, 2, 3]
n2 = NumList [4, 5, 6]

我想做的是:

n3 = n1 + n2 -- Should be [5, 7, 9]

我尝试将其定义为:

toList :: NumList n -> [Rational]
toList (NumList n) = n

(+) :: NumList -> NumList -> NumList
(+) x y = if length x == length y
          then
              zipWith (+) toList x toList y -- This probably isn't right, but I'll debug this later
          else
              error "NumLists must be same length to add"

我得到的错误是:

Ambiguous occurrence `+'
It could refer to either `NumList.+',
                             defined at NumList.hs:7:5
                          or `Prelude.+'

我看不出这是多么模棱两可,因为 Prelude.+ 适用于Num类,而 NumList.+ 仅适用于 NumList 类型。对此有何指导?还有一个小问题:有没有办法使用模式匹配从 (+) 函数中删除 if 表达式?

4

1 回答 1

2

现在的错误是(+)定义了两种类型的 s,一种用于 Prelude 和你的。您可以通过创建NumList该类型的实例来解决此问题Num

instance Num NumList where
  (+) nl1 nl2 = implementPlus
  (*) nl1 nl2 = implementTimes
  (-) nl1 nl2 = implementMinus
  abs nl = NumList (map abs (toList nl))
  signum nl = NumList (map signum (toList nl))
  fromInteger i = NumList [fromInteger i]

现在加法将调用implemenPlus,一切都会很棒。作为额外的奖励,您甚至可以编写数字文字,haskell 会推断它们是 aNumList并将它们变成一个元素的列表,非常适合编写大量它们。

另外,对于你的奖金问题,我会这样写

(NumList n1) + (NumList n2) = NumList $ zipWith (+) n1 n2

这是我期望使用它的结果,结果是最短列表的长度。如果你真的想让它爆炸,

 (NumList n1) + (NumList n2) |length n1 == length n2 =
                                NumList $ zipWith (+) n1 n2
                             | otherwise             = 
                                error "You done goofed"

这只是使用警卫,将它们视为加强型if。并且otherwise被简单地定义为

otherwise = True

在序曲中。

于 2013-10-19T02:49:43.733 回答