Why "fmap (replicate 3) Just" is of type "a & # 8594; [maybe]], In Haskell

I recently learn Haskell online with Teach you Haskell for great sound .

I have two questions:

  • fmap (replicate 3) is of type Functor f=> fa -> f [a] . Why can this be applied to Just ?

  • Also, why fmap (replicate 3) Just type a -> [Maybe a] , and not of type a -> Maybe [a] ?

+7
types functor haskell
source share
2 answers

This is easy to understand if you understand that you are fmap - above is a function, not a Maybe a value. The type Just is a -> Maybe a , so it falls into the functor (->) a , and not into the Maybe functor. Functor instance for functions looks like

 instance Functor ((->) a) where fmap gf = g . f 

therefore fmap just becomes a normal compound function! It means that

 fmap (replicate 3) Just 

coincides with

 replicate 3 . Just 

which most definitely has type a -> [Maybe a]


The explanation for a more typical type algebra should be to build the types and replace them until you can no longer. Let's start with our types, but with different variable names, to simplify their implementation:

 fmap :: Functor f => (a -> b) -> (fa -> fb) replicate :: Int -> c -> [c] Just :: x -> Maybe x 

Then for fmap (replicate 3) :

  (replicate 3) :: c -> [c] fmap :: (a -> b) -> (fa -> fb) 

So,

 (c -> [c]) ~ (a -> b) 

It means that

 c ~ a [c] ~ b b ~ [a] 

So, substituting back:

 fmap (replicate 3) :: fc -> f [c] 

Then what we fmap above is Just , which is of type

 Just :: x -> Maybe x 

What can be rewritten in the form of a prefix as

 Just :: (->) x (Maybe x) 

Or with lots of brackets if we really want

 Just :: ((->) x) (Maybe x) 

Then

  Just :: ((->) x) (Maybe x) fmap (replicate 3) :: fc -> f [c] 

It means that

 ((->) x) (Maybe x) ~ fc (->) x ~ f Maybe x ~ c [c] ~ [Maybe x] 

So, substituting back:

 fmap (replicate 3) :: ((->) x) (Maybe x) -> ((->) x) [Maybe x] 

And back to infix notation

 fmap (replicate 3) :: (x -> Maybe x) -> (x -> [Maybe x]) 

Then applying Just :

 fmap (replicate 3) Just :: x -> [Maybe x] 

Here I would like to emphasize that Maybe , which is a Functor , has nothing to do with this reduction, the only Functor is the Functor function. Lists are also Functor , but just because it is displayed in the replicate type does not mean that it is important in this case. Easy to confuse with function

 fmap (replicate 3) . Just :: a -> Maybe [a] 

but this is completely different due to the addition . .

+13
source share

The Functor instance that fmap uses is (->) r , not Maybe . Let's look at the types:

 replicate 3 :: a -> [a] fmap (replicate 3) :: Functor f => fa -> f [a] Just :: b -> Maybe b 
  • In the fmap (replicate 3) Just statement, we need to map the Functor f => fa to b -> Maybe b . The instance that this selects is an instance of (->) r (since Just is a function), and we get ((->) ra) -> ((->) r [a]) .
  • We can deploy these applications (->) to get this type (specialized for accepting a function as an argument): (r -> a) -> (r -> [a]) .
  • Next, to match the Just type, we need to match r with b and a with Maybe b (so that we can match (r -> a) with (b -> Maybe b) ), giving us (b -> Maybe b) -> (b -> [Maybe b]) .
  • This is a specialized type of fmap (replicate 3) that we can now apply to Just to get fmap (replicate 3) Just :: b -> [Maybe b] , which is the same as a -> [Maybe a] .

As a side note, the full fmap type specialized for the instance (->) r is fmap :: (a -> b) -> (r -> a) -> (r -> b) , which means it matches with the composition of the function: fmap = (.) .

+4
source share

All Articles