是否有更简单的方法(可能是标准功能):
(如果列表包含元素,则结果是该元素的下一个元素 列表;如果元素是列表的最后一个元素,则结果是第一个元素 的清单。 "特殊情况":如果列表为空,则结果为Nothing。如果是清单 不包含元素,结果是列表的第一个元素。)
import Data.List
next :: Eq a => Maybe a -> [a] -> Maybe a
next _ [] = Nothing
next Nothing (x:_) = Just x
next (Just x) list = Just $ list !! index
where index =
case elemIndex x list of
Nothing -> 0
Just xIndex ->
if xIndex + 1 == length list
then 0
else xIndex + 1
答案 0 :(得分:7)
让我们调用元素e
和列表xs
。如果将开头的所有元素与e
不等于dropWhile (/= e)
,则会更容易。之后,您可以专注于两种情况,我们将始终返回一个值:
(_:y:_)
上进行模式匹配,以便在e
之后获取元素并返回y
总的来说,我们得到了
next :: Eq a => Maybe a -> [a] -> Maybe a
next _ [] = Nothing
next Nothing (x:_) = Just x
next (Just e) l@(x:_) = Just $ case dropWhile (/= e) l of
(_:y:_) -> y
_ -> x
答案 1 :(得分:2)
首先,我要更改您的功能的签名,通常您不会定义仅适用于Maybe的功能。
所以我介绍一个函数,它返回给定元素之后的列表部分。
following :: (Eq a) => a -> [a] -> [a]
following _ [] = []
following x (y:l) = if x==y then l else following x l
然后我定义下一个返回'跟随x l'的第一个元素。或列表的第一个元素。
next :: (Eq a) => [a] -> a -> Maybe a
next [] _ = Nothing
next l x = if f == [] then Just(head l) else Just(head f)
where f = following x l
现在你可以使用' next'这样:
> l = 2 : 5 : 6 : 1 : []
> next l 5
6
> next l 7
2
如果你想打电话给下一个也许你可以使用一个可能是一个Monade的事实。
> Just 5 >>= next l
Just 6
注意:我交换了next的参数,以便更容易按照他的方式调用它。
答案 2 :(得分:1)
通过使用尾部压缩列表,我们获得了元素及其后继者的关联列表:
> lookup 1 $ (zip <*> tail) [1,2,3,4]
Just 2
> lookup 4 $ (zip <*> tail) [1,2,3,4]
Nothing
这也很懒惰:
> lookup 4 $ (zip <*> tail) [1..]
Just 5