当尝试使用 foldr 实现 dropWhile 时,我想出的第一个算法是
dropWhile' :: (a -> Bool) -> [a] -> [a]
dropWhile' pred = fst . foldr (\cur (acc, xs) ->
if pred cur
then (acc, cur:xs)
else (cur:xs, cur:xs)) ([], [])
Run Code Online (Sandbox Code Playgroud)
虽然这有效,但它会导致无限列表上的堆栈溢出而没有给出任何值。因为我不确定,为什么这不起作用,我只是玩弄这个函数,直到我想出这个:
dropWhile' :: (a -> Bool) -> [a] -> [a]
dropWhile' pred = fst . foldr (\cur t -> let (acc, xs) = t in
if pred cur
then (acc, cur:xs)
else (cur:xs, cur:xs)) ([], [])
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,这个和第一个之间的唯一区别是,这里我在(acc, xs)let 绑定中解构元组,而不是直接在函数参数内部解构。出于某种奇怪的原因,此代码适用于无限列表。如果有人知道为什么会这样,请告诉我。
我最近使用了 State Monad 内部的Map类型Data.Map,所以我想写一个函数,它在 Map 中查找一个值,并从 State Monad 内部的 Map 中删除它。我当前的实现如下所示:
lookupDelete :: (Ord k) => k -> State (Map k v) (Maybe v)
lookupDelete k = do
m <- get
put (M.delete k m)
return $ M.lookup k m
Run Code Online (Sandbox Code Playgroud)
虽然这有效,但感觉效率很低。使用命令式语言中的可变映射,找到delete函数并返回被删除的值的情况并不少见。我找不到这个功能,所以如果有人知道一个(或可以解释为什么没有),我将不胜感激
在 a 中存储数据时Map,我最近在寻找一个Bitraversable实例,因为我想遍历键和值。令我惊讶的是,我发现Map它甚至没有Bifunctor实例,即使first( mapKeys) 和second( map) 的实现都存在。
是否有特定原因,或者这个决定只是为了最大限度地减少依赖性?
谢谢