In the exercises I have implemented fmapT
:
-- Let's remind ourselves of Traversable, noting Foldable and Functor.
--
-- class (Foldable t, Functor t) => Traversable t where
-- traverse ::
-- Applicative f =>
-- (a -> f b)
-- -> t a
-- -> f (t b)
-- | Observe that @fmap@ can be recovered from @traverse@ using @Identity@.
--
-- /Reminder:/ fmap :: Functor t => (a -> b) -> t a -> t b
fmapT ::
Traversable t =>
(a -> b)
-> t a
-> t b
fmapT =
error "todo: fmapT"
Now how do I implement over
?
-- | Let's refactor out the call to @traverse@ as an argument to @fmapT@.
over ::
((a -> Identity b) -> s -> Identity t)
-> (a -> b)
-> s
-> t
over = error "undefined"
You can implement fmapT
using traverse
as:
fmapT f s = runIdentity (traverse (Identity . f) s)
now the next exercise is to refactor this function by providing traverse
as a parameter rather than hard-coding it in the definition. If you choose Identity
as the applicative type constructor then the type of traverse
is:
(Traversable t) => (a -> Identity b) -> t a -> Identity (t b)
if you provide this as a parameter to fmapT
you end up with something like over
:
over' :: Traversable t => ((a -> Identity b) -> t a -> Identity (t b)) -> (a -> b) -> t a -> t b
over' l f s = runIdentity (l (Identity . f) s)
since the Traversable
constraint exists in traverse
it is not required by over'
which has the more general type of over
given in the exercise i.e.
over :: ((a -> Identity b) -> (s -> Identity t)) -> (a -> b) -> s -> t
and
over' = over traverse