【问题标题】:How to detect the end of a list in Haskell?如何在 Haskell 中检测列表的结尾?
【发布时间】:2015-02-21 05:43:31
【问题描述】:

我正在编写一个使用特定公式计算 2 个列表的递归函数。 但我会简化函数,以便您了解我遇到的问题,因为这里的重点是检测列表的 []。

所以我有以下代码:

listSum::([Integer],[Integer])->Double
listSum ((x:xs),(y:ys)) 
    | ((x:xs),(y:ys))==(x:[],y:[])=0.0
    | otherwise = (((fromIntegral x)::Double)+((fromIntegral y)::Double)) + listSum ((xs),(ys))

我现在的输出

listSum([1,2],[1,2])
2.0

listSum([1],[1])
0.0

listSum([],[])
*** Exception: file.hs: .....: Non-exhaustive patterns in function ListSum

还有我想要的输出

listSum([1,2],[1,2])
6.0

listSum([1],[1])
2.0

listSum([],[])
0.0

我错过了什么?还是我写的太多了?

【问题讨论】:

  • 您通过[](例如myFunc [] = 0; myFunc (x:xs) = x + myFunc xs)上的模式匹配来检测列表的结尾
  • 第一件事就是告诉GHC-fwarn-incomplete-patterns

标签: list haskell non-exhaustive-patterns


【解决方案1】:

你的函数中不需要第一个守卫。你可以简单地写成下面这样(我刚刚删除了::Double,因为Haskell可以推断出来)

listSum :: ([Integer], [Integer]) -> Double
listSum ([], []) = 0.0
listSum ((x:xs),(y:ys)) = fromIntegral x + fromIntegral y + listSum (xs, ys)

现在,只要传递给listSum 的参数是空列表,结果将为0.0,否则将调用递归函数。

注意:仅当两个列表大小相等时,上述功能才有效。否则需要这样写

listSum::([Integer],[Integer])->Double
listSum ([], []) = 0.0
listSum ((x:xs), []) = fromIntegral x + listSum(xs, [])
listSum ([], (y:ys)) = fromIntegral y + listSum(ys, [])
listSum ((x:xs),(y:ys)) = fromIntegral x + fromIntegral y + listSum (xs, ys)

注意:更简单,整个代码可以写成as suggested by Rein Henrichs,像这样

pairwiseSum xs ys = sum (zipWith (+) xs ys)

【讨论】:

  • 这仍然有不完整的模式!
  • @dfeuer 我认为在 OP 的情况下,两个列表的大小相同。
  • 是的,就我而言,两个列表的大小相同。谢谢thefourtheye,非常好的解释。它有效。
  • @dfeuer 好的,那我错过了一些东西。可以举个例子吗?
  • @Dogbert 我特别避免使用无点版本,因为它会降低可读性而无济于事。这是毫无意义的无意义的完美示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-12
  • 1970-01-01
  • 2015-03-06
  • 2015-08-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多