簡體   English   中英

mapMaybe 用於 Data.Map 中的鍵

[英]mapMaybe for keys in Data.Map

我想 map 下面的 function 超過一個Map的鍵

f :: a -> Maybe b

並丟棄Nothing鍵並保留Just鍵,但從Just中提取。 就像Map.mapMaybe一樣,但是對於鍵

mapMaybeKeys :: (a -> Maybe b) -> Map a c -> Map b c

我在 Hoogle 中搜索了這種類型的簽名,但沒有找到任何東西。

我可以這樣做:

mapMaybeKeys f
    = Map.toList
    . catMaybes
    . fmap (fmap swap . traverse f . swap)
    . Map.toList

或者:

mapMaybeKeys f
   = Map.mapKeys fromJust
   . Map.delete Nothing
   . Map.mapKeys f

有沒有更優雅的方式?

使用列表推導,

import Data.Map (Map)
import qualified Data.Map as M
import Control.Arrow (first)

mapMaybeKeys :: Ord b => (a -> Maybe b) -> Map a c -> Map b c
mapMaybeKeys f m = 
   M.fromList [ (b,a) | (Just b, a) <- map (first f) . M.toList $ m ]

foldMapWithKey (或foldrWithKey )還不錯,無需經過中間列表。

mapMaybeKeys :: (Ord b) => (a -> Maybe b) -> Map a c -> Map b c

mapMaybeKeys f = Map.foldMapWithKey
  (\ k a -> foldMap (\ k' -> M.singleton k' a) (f k))

-- or:
mapMaybeKeys f = Map.foldMapWithKey (flip (foldMap . flip M.singleton) . f)

-- or:
mapMaybeKeys = M.foldMapWithKey . fmap (flip (foldMap . flip M.singleton))

如果鍵 function 返回Nothing ,則內部foldMap會生成一個空的 map 。 您可以添加一些輔助定義,通過避免flip來使其成為看起來更簡單的合成管道。 請注意,您需要Ord約束才能使用b作為生成的 map 的鍵。

謝謝@Will Ness 和@Jon Purdy,我喜歡你的解決方案,但經過一些調整,我認為我最喜歡我原來的解決方案:

import Data.Bitraversable (bitraverse)
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Maybe (catMaybes)

mapMaybeKeys :: (Ord b) => (a -> Maybe b) -> Map a c -> Map b c
mapMaybeKeys f
  = Map.fromList
  . catMaybes
  . fmap (bitraverse f Just)
  . Map.toList

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM