在haskell中另一个元素出现之前返回元素

时间:2016-08-07 02:41:42

标签: list haskell functional-programming

我想在Haskell中编写一个代码,以便在列表中另一个元素出现之前返回一个元素。例如:

ePefore 3 [1,2,3,4,5]应返回2

我对哈斯克尔很安静。我到目前为止编写的代码是:

eBefore :: Eq a => a -> [a] -> Maybe a
eBefore n [] = Nothing
eBefore n (x:xs) = if x == n then Just x else eBefore n xs

如果有人能够帮助我理解这个方法或帮助解决问题,我将非常感激。谢谢!

1 个答案:

答案 0 :(得分:2)

您可以匹配更精细的图案:

eBefore n [] = Nothing
eBefore n [_] = Nothing
eBefore n (x1:xs@(x2:_))
    | x2 == n   = Just x1
    | otherwise = eBefore n xs

这里我们为包含零个或一个元素的列表返回Nothing,因为它们不包含前面有另一个元素的成员。 (x1:xs@(x2:_))是与x1:xs匹配的模式,其中xs依次匹配x2:_,即包含至少两个元素的列表,第一个元素绑定到{ {1}},第二个x1,残差不重要(由x2匹配)。

我们也可以这样写:

_

但是,这种变体在性能方面可能更差。 eBefore n [] = Nothing eBefore n [_] = Nothing eBefore n (x1:x2:xs) | x2 == n = Just x1 | otherwise = eBefore n (x2:xs) 相当于(x1:x2:xs),我们看到(x1:(x2:xs))再次作为递归调用的参数重复。但是编译器可能无法识别两个表达式的标识并创建新节点。那是浪费。通过在前一个变体中使用(x2:xs) - 表示法,我们从模式中为@提供一个名称(x2:_),并将其作为一个完整的整体传递给递归调用。

这里的困难时刻是我们应该返回xs等于列表头部的情况,例如: G。 n。上面的定义将跳过第一次出现的3并返回6.