Бихте искали обектив като
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
вместо това
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)
така че често е по-добре да избягвате тези псевдолещи, за да предотвратите злополуки.
person
J. Abrahamson
schedule
12.03.2014