Differences
This shows you the differences between two versions of the page.
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> |