我想返回列表中元素的前一个元素。我打算得到参数的索引,并使用它来表示反对列表,这样参数是最后一个元素,然后反转它,然后取反列表的第二个元素。我得到了错误:输入elemIndex是Maybe Int,而take函数需要Int。我想要修复它或者用简单的递归编写代码,是否有更短的使用递归的代码?
precedingElement :: Eq a => a -> [a] -> Maybe a
precedingElement elt lst | lst == [] = error "List is empty"
| elt `notElem` lst = Nothing
| otherwise = Just x where x = snd (reverse (take (elt `elemIndex` lst) lst))发布于 2016-08-16 01:27:20
为了返回给定元素的前一个元素,可以使用一些模式匹配和递归:
precedingElement _ [] = Nothing
precedingElement _ [x] = Nothing
precedingElement elt (x:y:rest)
| y == elt = Just x
| otherwise = precedingElement elt (y:rest)发布于 2016-08-16 08:38:09
对于这样的问题,我最喜欢的一个被低估的实用程序相当方便。让我有倒向列表,这样我就不需要反转我的大脑了。
data Bwd x = B0 | Bwd x :< x -- rightmost is nearest把列表元素想象成算盘线上的珠子。向左轻击几下,让你的手指放在下一个上。你有什么?手指左边的珠子列表(最右边的),手指右边的珠子列表(最左边的珠子),还有你手指上的珠子。
也就是说,列表的单孔元素上下文是由孔的任何一边的前向和后向列表给出的。
type ListContext x = (Bwd x, [x])那些知道我的老歌的人认为ListContext是[]的衍生词。
焦点的一个元素(你的手指在珠上)是
type ListFocus x = (ListContext x, x)还有一个有用的操作,用它的上下文装饰每个list元素,并将其放在焦点上。
focus :: [x] -> [ListFocus x]
focus = go B0 where
go xz [] = []
go xz (x : xs) = ((xz, xs), x) : go (xz :< x) xs例如,
focus [1,2,3] = [((B0,[2,3]),1), ((B0 :< 1,[3]),2), ((B0 :< 1 :< 2,[]),3)]现在很容易回答与元素及其周围环境有关的各种问题。您可能不应该仅仅为了解决这个问题而构造focus,但这是我一直关注的事情,因为它解决了许多问题。
[p | ((_ :< p,_),q) <- focus xs, q == x]计算位于p中x左侧的所有值xs。如你所见。
(顺便说一句,这个focus操作不是从哪里来的。它源于列表的数据类型的差异结构。This answer (在这里被称为picks)更详细地讲述列表故事,this answer开发了数据类型通用故事。
发布于 2016-08-16 03:44:01
因为我是一个狂热的粉丝,我可能会写一些东西
lastBefore :: (a -> Bool) -> [a] -> Maybe a
lastBefore p xs = foldr go (`seq` Nothing) xs Nothing
where
go x r (Just prev) | p x = Just prev
go x r _ = r (Just x)但我必须检查GHC是否可以按我的意愿优化它。
https://stackoverflow.com/questions/38965291
复制相似问题