10

私はlensHaskell のライブラリに慣れようとしていますが、いくつかの単純な問題に苦労していることに気づきました。たとえば、(便宜上)次のタイプがあるatとしましょう(_1少なくとも、これが私が理解している方法です):

at :: Ord k => k -> Lens' (Map k v) (Maybe v)

_1 :: Lens' (a, b) a

これらのレンズを次のタイプのレンズに組み合わせるにはどうすればよいですか。

maybeFst :: Ord k => k -> Lens' (Map k (a, b)) (Maybe a)
4

1 に答える 1

8

こんなレンズが欲しい

Lens' (Maybe (a, b)) (Maybe a)

Lensしかし、元に戻すと にもNothing影響するため、それは完全にはできませんb。それはすることができますGetter

getA :: Getter (Maybe (a, b)) (Maybe a)
getA = to (fmap fst)

しかし、それを作成するとGetter、完全ではなく、同様に終了しますLens

maybeFst :: Ord k => k -> Getter (Map k (a, b)) (Maybe a)
maybeFst k = at k . getA

おそらくそれよりも良いのは、Traversal代わりにa を使用することです

maybeFstT :: Ord k => k -> Traversal' (Map k (a, b)) a
maybeFstT k = at k . _Just . _1

これにより、マップ内の値の値を取得 (previewまたはを使用toListOf) および設定するfstことができますが、マップ内のその存在を変更することはできません: 値が存在しない場合は追加できません。削除することはできません。


最後に、適切なタイプのフェイクLensを仮装することができますが、デフォルト値を与える必要があります。b

getA :: b -> Lens' (Maybe (a, b)) (Maybe a)
getA b inj Nothing       = (\x -> (,b) <$> x) <$> inj Nothing
getA _ inj (Just (a, b)) = (\x -> (,b) <$> x) <$> inj (Just a)

しかし、あまり似ていない動作があることに注意してLensください。

>>> Just (1, 2) & getA 0 .~ Nothing & preview (_Just . _2)
Nothing

>>> Nothing & getA 0 .~ Just 1
Just (1,0)

多くの場合、事故を防ぐためにこれらの疑似レンズを使用しない方がよいでしょう。

于 2014-03-12T20:49:34.163 に答える