Search code examples
haskellfunctor

About some basic functor in haskell


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"]