Ответ 1
Вам нужен объектив, например
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)
но обратите внимание, что он имеет некоторое не очень-тесное поведение.
>>> Just (1, 2) & getA 0 .~ Nothing & preview (_Just . _2)
Nothing
>>> Nothing & getA 0 .~ Just 1
Just (1,0)
так часто лучше избегать этих псевдоуровней, чтобы предотвратить неудачи.