Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
pp:functors [2021/04/19 09:48]
pdmatei [6. Functors, Foldables]
pp:functors [2021/04/21 15:51] (current)
alexandru.rait Changed 6 to 7 in title
Line 1: Line 1:
-====== ​6. Functors, Foldables ======+====== ​7. Functors, Foldables ======
  
-Functors are data types over which we can ''​map''​ a function (that is, apply a function on each element while keeping the overall structure). You've already encountered a Functor, namely haskell lists. For historical reasons, ''​map''​ only works on lists (''​map :: (a -> b) -> [a] -> [b]''​),​ but there exists a more general function ''​fmap''​ (''​fmap :: (Functor f) => (a -> b) -> f a -> f b''​).+Functors are data types over which we can ''​map''​ a function (that is, apply a function on each element while keeping the overall structure). You've already encountered a Functor, namely haskell lists. For historical reasons, ''​map''​ only works on lists (''​map :: (a -%%>%% b) -%%>%% [a] -%%>%% [b]''​),​ but there exists a more general function ''​fmap''​ (''​fmap :: (Functor f) =%%>%% (a -%%>%% b) -%%>%% f a -%%>%% f b''​).
  
 The class definition looks like this: The class definition looks like this:
Line 10: Line 10:
 </​code>​ </​code>​
     ​     ​
-Notice (based on the types ''​f a''​ and ''​f b''​) that what is enrolled in ''​Functor''​ is not a data type, but a data constructor with kind ''​* -> *''​. Thus we say that ''​[]'',​ ''​Maybe''​ are functors, and **not** ''​[Int]'',​ ''​[a]'',​ ''​Maybe Char'',​ ''​Maybe a''​ etc.+Notice (based on the types ''​f a''​ and ''​f b''​) that what is enrolled in ''​Functor''​ is not a data type, but a type constructor with kind ''​* -%%>%% *''​. Thus we say that ''​[]'',​ ''​Maybe''​ are functors, and **not** ''​[Int]'',​ ''​[a]'',​ ''​Maybe Char'',​ ''​Maybe a''​ etc.
  
-Can a pair ''​(,​)''​ be a functor? The answer is no, because the type constructor has kind ''​(,​) :: * -> * -> *''​. However, we can partially apply to a specific type and make the resulting ''​* -> *''​ constructor a ''​Functor''​. The haskell syntax for this is as follows (this already exists in ''​Prelude''​):​+Can a pair ''​(,​)''​ be a functor? The answer is no, because the type constructor has kind ''​(,​) :: * -%%>%% * -%%>%% *''​. However, we can partially apply to a specific type and make the resulting ''​* -%%>%% *''​ constructor a ''​Functor''​. The haskell syntax for this is as follows (this already exists in ''​Prelude''​):​
  
 <code haskell> <code haskell>
Line 86: Line 86:
 </​code>​ </​code>​
  
-Now our functions work and can handle the empty list without throwing an exception. However, it should be obvious that we now need to change any ''​Int -> a''​ function we want to apply on our result to a ''​Maybe Int -> Maybe a''​ function, which seems like a lot of work. Plus the change will be as dull in all cases:+Now our functions work and can handle the empty list without throwing an exception. However, it should be obvious that we now need to change any ''​Int -%%>%% a''​ function we want to apply on our result to a ''​Maybe Int -%%>%% Maybe a''​ function, which seems like a lot of work. Plus the change will be as dull in all cases:
  
   - if we get a ''​Nothing'',​ we return a ''​Nothing''​   - if we get a ''​Nothing'',​ we return a ''​Nothing''​
   - if we get a ''​Just'',​ we unpack it, do with it what the function did originally, then repack it in a ''​Just''​.   - if we get a ''​Just'',​ we unpack it, do with it what the function did originally, then repack it in a ''​Just''​.
  
-It would be great if we could just have a function which does this transformation for us. And we do. Remember currying and how multiple-argument functions actually take on argument and return another function and so on. Thus we can reinterpret ''​fmap'''​s signature as: ''​(a -> b) -> (f a-> (f b)''​. That is: it takes a function from ''​a''​ to ''​b''​ and returns a function from a functor ''​a''​ to a functor ''​b''​. Set the functor ''​f''​ to ''​Maybe''​ and that'​s ​ it!+It would be great if we could just have a function which does this transformation for us. And we do. Remember currying and how multiple-argument functions actually take on argument and return another function and so on. Thus we can reinterpret ''​fmap'''​s signature as: ''​(a -%%>%% b) -%%>%% (f a -%%>%% f b)''​. That is: it takes a function from ''​a''​ to ''​b''​ and returns a function from a functor ''​a''​ to a functor ''​b''​. Set the functor ''​f''​ to ''​Maybe''​ and that'​s ​ it!
  
 <code haskell> <code haskell>