Parametric polymorphism: Difference between revisions
Content added Content deleted
(add E example) |
(→{{header|Haskell}}: discuss fmap) |
||
Line 152: | Line 152: | ||
=={{header|Haskell}}== |
=={{header|Haskell}}== |
||
<lang haskell> |
<lang haskell>data Tree a = Empty | Node a (Tree a) (Tree a) |
||
mapTree :: (a -> b) -> Tree a -> Tree b |
|||
mapTree f Empty = Empty |
|||
mapTree f (Node x l r) = Node (f x) (mapTree f l) (mapTree f r)</lang> |
|||
<blockquote><small> |
|||
A digression: |
|||
Note that for the most usefulness in practical programming, a map operation like this should not be defined with a separate name but rather as <code>fmap</code> in an ''instance'' of the <code>Functor</code> ''type class'': |
|||
<lang haskell>instance Functor Tree where |
|||
fmap f Empty = Empty |
|||
fmap f (Node x l r) = Node (f x) (fmap f l) (fmap f r)</lang> |
|||
<code>fmap</code> can then be used exactly where <code>mapTree</code> can, but doing this also allows the use of <code>Tree</code>s with other components which are parametric over ''any type which is a Functor''. For example, this function will add 1 to any collection of any kind of number: |
|||
<lang haskell>add1Everywhere :: (Functor f, Num a) => f a -> f a |
|||
add1Everywhere nums = fmap (\x -> x + 1) nums</lang> |
|||
If we have a tree of integers, i.e. <var>f</var> is <code>Tree</code> and <var>a</var> is <code>Integer</code>, then the type of <code>add1Everywhere</code> is <code>Tree Integer -> Tree Integer</code>. |
|||
</small></blockquote> |
|||
=={{header|Java}}== |
=={{header|Java}}== |