Why does this fmap (replicate 3) Just "JOHN" return this [Just "JOHN",Just "JOHN",Just "JOHN"] ? I know that fmap (replicate 3) Just "JOHN" is equivalent with fmap (replicate 3) Just $ "JOHN", but why does that even compile ? How can we apply fmap to
Just which isn’t even of concrete type ?
>Solution :
A functor f is a type constructor with an associated function fmap that "lifts" a function of type a -> b to be a function of type f a -> f b.
Both Maybe and (->) r (the partially applied function constructor) are functors.
-- When possible, apply the function to the wrapped value
-- and wrap the result. Otherwise, return Nothing
instance Functor Maybe where
fmap f Nothing = Nothing
fmap f (Just x) = Just (f x)
-- Compose the two functions
instance Functor ((->) r) where
fmap f g = f . g
Your expression uses the function instance on the two functions replicate 3 :: a -> [a] and Just :: a -> Maybe a:
fmap (replicate 3) Just "JOHN" == (replicate 3) . Just $ "JOHN"
== (replicate 3) (Just "JOHN")
== [Just "JOHN", Just "JOHN", Just "JOHN"]
What you likely intended was to map replicate 3 over the value Just "JOHN" :: Maybe String, making use of the Maybe instance.
fmap (replicate 3) (Just "JOHN") == Just (replicate 3 "JOHN")
== Just ["JOHN", "JOHN", "JOHN"]