以下是产生错误的代码示例:
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很陌生,所以如果这是一个愚蠢的错误,我会支持。
答案 0 :(得分:4)
您编写的类型签名描述了三个Ints的列表:[Int, Int, Int]
。然而,列表类型具有不确定的长度,并且您编写的金额函数似乎期望3个元组的Ints,其将被写为[(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
现在任何长度的列表都会传递给map
,这很好,因为它意味着处理任意长度。实际上sum
也是如此,所以我们甚至不需要为空列表添加特殊情况。
如果您要为长于一个的列表添加模式,则传统表单为x:xs
,将其分为头x
和尾xs
。该模式与空列表不匹配,因为它无法拆分。
原始代码的问题还在于它只定义了一个元组列表的版本。我们可以使用列表推导或映射来处理:
amount1 abcs = sum [c | (a,b,c) <- abcs]
amount2 = sum . map (\(a,b,c) -> c)
所有这些变体做同样的事情,即使amount2甚至没有提到一个论点。
答案 1 :(得分:1)
首先,你的类型签名是错误的,它必须是
amount :: [(Int, Int, Int)] -> Int
出现“非穷尽模式错误,因为您只提供了两种列表:
在底部是空列表[]的情况,在上面的情况下,列表包含一个元素
([(a,b,c)]
是一个包含元素(a,b,c)
的列表。因此,您的代码可以使用amount [(1,2,3)]
)
最简单的方法:将[(a,b,c)]
替换为xs
,位于=和右侧的左侧。
答案 2 :(得分:0)
(a,b,c)
是一个元组:(a,b,c) = (,,) a b c
amount :: [(Int, Int, Int)] -> Int
amount [(a, b, c)] = ...
正确的
答案 3 :(得分: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 = (+)