haskell产生式中的和函数&x27;非穷举模式';错误
下面是产生错误的代码示例:haskell产生式中的和函数&x27;非穷举模式';错误,haskell,Haskell,下面是产生错误的代码示例: 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( 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]
但我试着重写和添加一些东西,看看是否能找到错误的原因,但我做不到。我对哈斯凯尔相当陌生,所以如果这是一个愚蠢的错误,我很抱歉。(a,b,c)
是一个元组:(a,b,c)=(,)ab c
amount :: [(Int, Int, Int)] -> Int
amount [(a, b, c)] = ...
右边的元组是一个元组:(a,b,c)=(,)abc
amount :: [(Int, Int, Int)] -> Int
amount [(a, b, c)] = ...
正确的首先,您的类型签名是错误的,必须是
amount :: [(Int, Int, Int)] -> Int
出现“非穷举模式错误”,因为您只提供了两种情况的列表:
底部为空列表[]的大小写,上方为大小写,其中列表包含一个元素
([(a,b,c)]
是包含元素(a,b,c)
的列表。因此,您的代码将使用金额[(1,2,3)]
)
最简单的方法是:在=的左侧和右侧,将
[(a,b,c)]
替换为xs
。首先,您的类型签名是错误的,它必须是正确的
amount :: [(Int, Int, Int)] -> Int
出现“非穷举模式错误”,因为您只提供了两种情况的列表:
底部为空列表[]的大小写,上方为大小写,其中列表包含一个元素
([(a,b,c)]
是包含元素(a,b,c)
的列表。因此,您的代码将使用金额[(1,2,3)]
)
最简单的方法是:将
[(a,b,c)]
替换为xs
,位于=的左侧和右侧。您编写的类型签名描述了三个Int的列表:[Int,Int,Int]
。然而,列表类型的长度是不确定的,您编写的amount函数似乎需要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
现在,任何长度的列表都将传递给map
,这很好,因为它可以处理任意长度的列表。实际上,sum
,因此我们甚至不需要为空列表添加特殊情况
如果要为多个列表添加一个模式,传统的形式是x:xs
,将其分解为头x
和尾xs
。该模式与空列表不匹配,因为它无法拆分
原始代码的问题还在于它只为一个元组列表定义了一个版本。我们可以使用列表理解或映射来处理:
amount1 abcs = sum [c | (a,b,c) <- abcs]
amount2 = sum . map (\(a,b,c) -> c)
amount1 abcs=sum[c |(a,b,c)c)
所有这些变体都做同样的事情,尽管amount2甚至没有提到参数。您编写的类型签名描述了三个Int的列表:
[Int,Int,Int]
。但是,列表类型的长度不确定,您编写的amount函数似乎需要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
现在,任何长度的列表都将被传递到map
,这很好,因为它是用来处理任意长度的。sum
,实际上也是如此,所以我们甚至不需要为空列表添加特殊情况
如果要为一个以上的列表添加模式,传统形式是x:xs
,将其分解为头x
和尾xs
。该模式与空列表不匹配,因为它无法拆分
原始代码的问题还在于它只为一个元组的列表定义了一个版本。我们可以使用列表理解或映射来处理该问题:
amount1 abcs = sum [c | (a,b,c) <- abcs]
amount2 = sum . map (\(a,b,c) -> c)
amount1 abcs=sum[c |(a,b,c)c)
所有这些变体都做了相同的事情,尽管amount2甚至没有提到参数。我当然不建议在“严重”代码中使用
Int
aMonoid
,但它可以工作:
我当然不建议在“严重”代码中使用
Int
aMonoid
,但它会起作用:
作为一种风格,你真的应该把它写成
sum(mapgetbalance[(a,b,c)])
。括号表示一个子表达式,而不是函数应用程序。它们应该紧紧围绕该子表达式。haskell是一种漂亮的语言,所以样式总是有用的。从风格上讲,你真的应该把它写成sum(map getBalance[(a,b,c)])
。括号表示子表达式,而不是函数应用程序。它们应该紧紧围绕该子表达式。haskell是一种漂亮的语言,因此样式总是有用的。感谢您提供详细的答案。我实际上有[(Int,Int,Int)]使用我自己定义的类型,并将其更改为便于理解的帖子。哎呀。但是你的回答非常有用:)。只是为了确保我理解正确。当[(a,b,c)]在函数的左侧,它是否将其视为具有一个元组元素的列表,而不是元组列表?在解决方案中,它仅在将其视为具有列表类型的单个变量时才对列表起作用?是的,在模式匹配中[(a,b,c)]是一个包含一个3元组的列表,而在类型签名中,它表示(任意数量的)的列表3元组。映射ide的参数