In the code it works well as below
divide :: Int -> Int -> Either String Int
divide a 0 = Left "Error with 0"
divide a b = Right (a `div` b)
The code to be changed
Map.adjust (divide 3) "A" $ Map.fromList [("A",3),("B",0)]
The expected result should be :
Map.adjust (divide 3) "A" $ Map.fromList [("A",3),("B",0)]
=> Right $ Map.fromList [("A",1),("B",0)]
Map.adjust (divide 3) "B" $ Map.fromList [("A",3),("B",0)]
=> Left "Error with 0"
Or in general how to build a function like:
Map.adjust:: (a -> m a) -> k -> (Map k a) -> m (Map k a)
Thank you very much !
A function adjustM
with type (a -> m a) -> k -> (Map k a) -> m (Map k a)
can be defined on top of the already existing function alterF :: (Functor f, Ord k) => (Maybe a -> f (Maybe a)) -> k -> Map k a -> f (Map k a)
.
alterF
is more general because, besides allowing for effects, it also lets you remove the targeted value, or insert it when the key doesn't already exist. (That's what those Maybe
s are for in its signature).
adjustM :: (Ord k, Applicative m) => (a -> m a) -> k -> Map k a -> m (Map k a)
adjustM f = Map.alterF (\ma -> case ma of
-- No value? We do nothing.
Nothing -> pure Nothing
-- There's a value? We transform it.
Just v -> Just <$> f v)
Or, more succinctly,
adjustM :: (Ord k, Applicative m) => (a -> m a) -> k -> Map k a -> m (Map k a)
adjustM f = Map.alterF (traverse f)