我想返回列表中某个元素的前一个元素。我打算获取参数的索引并使用它来弃用列表,使参数是最后一个元素,然后将其反转并获取反转列表的第二个元素。
我收到错误:类型 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))
最佳答案
我最喜欢的未被充分重视的实用程序之一对于解决此类问题非常方便。让我有倒退的 list ,这样我就不需要倒转我的大脑了。
data Bwd x = B0 | Bwd x :< x -- rightmost is nearest
将列表元素想象成算盘线上的珠子。向左轻拂几个,然后将手指放在下一个上。你有什么?你手指左边的珠子列表(最右边的最近),你手指右边的珠子列表(最左边的最近),还有你手指放在上面的珠子。
也就是说,列表的单孔元素上下文由孔两侧的一对后向和前向列表给出。
type ListContext x = (Bwd x, [x])
知道我的老歌的人都知道 ListContext
是 []
的衍生物。
焦点元素(你的手指放在珠子上)是
type ListFocus x = (ListContext x, x)
还有一个有用的操作,它用上下文装饰每个列表元素,使其成为焦点。
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]
计算 xs
中 x
左侧的所有值 p
。 如您所见。
(顺便说一下,这个focus
操作不是凭空而来的。它源于列表数据类型的差异结构。This answer(它被称为picks
) 更详细地讲述了列表故事,this answer 开发了数据类型通用故事。)
关于list - 在列表中查找元素的前一个元素(Haskell),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38965291/