我想在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
如果有人能够帮助我理解这个方法或帮助解决问题,我将非常感激。谢谢!
答案 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.