Parametric polymorphism: Difference between revisions
Content added Content deleted
(→{{header|Haskell}}: discuss fmap) |
(Derived a Clean implementation based on the Haskell one) |
||
Line 59: | Line 59: | ||
right->replace_all (new_value); |
right->replace_all (new_value); |
||
}</lang> |
}</lang> |
||
=={{header|Clean}}== |
|||
<lang clean>::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 clean>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 clean>add1Everywhere :: (f a) -> (f a) | Functor f & Num 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|D}}== |
=={{header|D}}== |
||
D template can parametric by constant. |
D template can parametric by constant. |
||
Line 167: | Line 193: | ||
fmap f (Node x l r) = Node (f x) (fmap f l) (fmap f r)</lang> |
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 |
<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 |
<lang haskell>add1Everywhere :: (Functor f, Num a) => f a -> f a |