Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

confusion on using functor <$>

Why does the code of line

generateScripts pb = (greet <$>) <$> (maybeName <$> pb

have an extra functor after greet? Based on my understanding, I know that the LHS function will be used on the RHS but since there is an extra functor, I don't understand how it works.

maybeName :: (String, String) -> Maybe String
maybeName p = if length (snd p) == 10 then Just (fst p) else Nothing

generateScripts :: [(String, String)] -> [Maybe String]
generateScripts pb = (greet <$>) <$> (maybeName <$> pb)
    where greet = ("Hello "++)

phonebook = [ ("Bob",   "0178866524"), ("Fred",  "01624556442"), ("Alice", "0188998533") ]
GHCi> phonebook = [ ("Bob",   "0178866524"), ("Fred",  "01624556442"), ("Alice", "0188998533") ]
GHCi> generateScripts phonebook
[Just "Hello Bob",Nothing,Just "Hello Alice"]
like image 750
Saki Avatar asked Jan 27 '23 05:01

Saki


1 Answers

pb is a list of (String, String) tuples.

maybeName <$> pb maps maybeName over that list, giving [Maybe String] (a list of Maybes). The functor in question is [].

(greet <$>) <$> ... maps (greet <$>) over that list, i.e. it applies (greet <$>) to each element of the list (the elements having type Maybe String). The functor in question is [].

(greet <$>) maps greet over Maybe String. The functor in question is Maybe.

In general, if you have a function f :: a -> b, then (f <$>) :: (Functor f) => f a -> f b, and ((f <$>) <$>) :: (Functor f, Functor g) => g (f a) -> g (f b). Every <$> maps over another layer of functor.

In this case we have g = [] and f = Maybe, so this effectively makes greet :: String -> String operate on a structure where strings are nested two levels deep, such as [Maybe String].

like image 189
melpomene Avatar answered Jan 30 '23 14:01

melpomene