Вы хотели бы объектив, как
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