1

这是产生错误的代码示例:

amount :: [Int, Int, Int] -> Int
amount [(a, b, c)] = sum( map getBalance [(a, b, c)])
                         where getBalance :: (Int,Int,Int) -> Int
                               getBalance (d, e, f) = f
amount [] = 0

最初的代码只是:

amount :: [Int, Int, Int] -> Int
amount [(a, b, c)] = sum [c]

但是我尝试重写和添加一些东西,看看我是否能找到错误的原因,但我不能。我对 Haskell 很陌生,所以如果这是一个愚蠢的错误,我会道歉。

4

4 回答 4

4

您编写的类型签名描述了三个 Ints 的列表:[Int, Int, Int]. 但是,列表类型的长度不确定,并且您编写的数量函数似乎期望 Ints 的 3 元组,可以写为[(Int, Int, Int)]; 无论如何,这可以从定义中得出。因此将第一个代码块加载到 ghci 中会产生:

test.hs:1:11:
    Illegal type: '[Int, Int, Int]

一旦我提供更长的输入列表,就会出现第二个错误:

*Main> amount [(1,2,3),(4,5,6)]
*** Exception: test.hs:(2,1)-(5,13): Non-exhaustive patterns in function amount

这里的问题是两种模式都不匹配:您的列表模式具有一个或零个条目,但没有更多。看到这[(a, b, c)]是一个重复的表达式,我们直接替换它怎么样?

amount [] = 0
amount xs = sum( map getBalance xs)
                     where getBalance :: (Int,Int,Int) -> Int
                           getBalance (d, e, f) = f

现在任何长度的 list 都将被传递给map,这很好,因为它旨在处理任意长度。事实上,所以sum我们甚至不需要为空列表添加特殊情况。

如果您想为长于一个的列表添加模式,传统的形式是x:xs将其分解为 headx和 tail xs。该模式与空列表不匹配,因为它无法拆分。

您的原始代码的问题还在于它只为一个元组列表定义了一个版本。我们可以使用列表推导或映射来处理:

amount1 abcs = sum [c | (a,b,c) <- abcs]
amount2 = sum . map (\(a,b,c) -> c)

所有这些变体都做同样的事情,即使 amount2 甚至没有提到参数。

于 2013-09-28T19:51:13.760 回答
1

首先,你的类型签名是错误的,它必须是

amount :: [(Int, Int, Int)] -> Int

发生“非详尽模式错误”,因为您只提供了两种列表情况:在底部是空列表 [] 的情况,在情况上方,列表包含一个元素 ([(a,b,c)]是带有元素的列表(a,b,c)。因此,您的代码可以使用amount [(1,2,3)]

最简单的方法:在 = 的左边和右边[(a,b,c)]用,替换。xs

于 2013-09-28T19:45:15.290 回答
0

(a,b,c)是一个元组:(a,b,c) = (,,) a b c

amount :: [(Int, Int, Int)] -> Int
amount [(a, b, c)] = ...

正确的那一个

于 2013-09-28T19:44:10.137 回答
0

我当然不建议制作Int一个Monoid“严肃”的代码,但它起作用:

import qualified Data.Foldable as F
import Data.Monoid

amount :: [(Int,Int,Int)] -> Int
amount xs = let (_,_,x) = F.fold xs in x 

instance Monoid Int where
  mempty = 0
  mappend = (+)
于 2013-09-29T15:14:31.203 回答