Parametric polymorphism: Difference between revisions

Added Prolog
(Added a procedure "initTree", a procedure "map", a procedure "print" and an example.)
(Added Prolog)
 
(12 intermediate revisions by 9 users not shown)
Line 15:
 
=={{header|Ada}}==
<langsyntaxhighlight lang="ada">generic
type Element_Type is private;
package Container is
Line 28:
Right : Node_Access := null;
end record;
end Container;</langsyntaxhighlight>
<langsyntaxhighlight lang="ada">package body Container is
procedure Replace_All(The_Tree : in out Tree; New_Value : Element_Type) is
begin
Line 40:
end if;
end Replace_All;
end Container;</langsyntaxhighlight>
 
=={{header|C}}==
If the goal is to separate algorithms from types at compile typetime, C may do it by macros. Here's sample code implementing binary tree with node creation and insertion:<syntaxhighlight lang C="c">#include <stdio.h>
#include <stdlib.h>
 
Line 89:
 
return 0;
}</langsyntaxhighlight>
Comments: It's ugly looking, but it gets the job done. It has the drawback that all methods need to be re-created for each tree data type used, but hey, C++ template does that, too.
 
Line 95:
 
=={{header|C sharp|C#}}==
<langsyntaxhighlight lang="csharp">using System;
 
class BinaryTree<T>
Line 121:
return tree;
}
}</langsyntaxhighlight>
 
Creating a tree of integers and using Map to generate a tree of doubles with every node half the value of the first:
 
<langsyntaxhighlight lang="csharp">class Program
{
static void Main(string[] args)
Line 135:
BinaryTree<double> b2 = b.Map(x => x * 0.5);
}
}</langsyntaxhighlight>
 
{{anchor|C# modern version}}A version using more modern language constructs:
<langsyntaxhighlight lang="csharp">using System;
 
class BinaryTree<T>
Line 186:
}
}
</syntaxhighlight>
</lang>
 
{{out}}
Line 199:
=={{header|C++}}==
 
<langsyntaxhighlight lang="cpp">template<classtypename T>
class tree {
{
T value;
tree *left;
Line 207 ⟶ 206:
public:
void replace_all (T new_value);
};</langsyntaxhighlight>
 
For simplicity, we replace all values in the tree with a new value:
 
<langsyntaxhighlight lang="cpp">template<class T>
void tree<T>::replace_all (T new_value) {
{
value = new_value;
if (left != NULLnullptr)
left->replace_all (new_value);
if (right != NULLnullptr)
right->replace_all (new_value);
}</langsyntaxhighlight>
 
=={{header|C3}}==
<syntaxhighlight lang="c3">module tree(<Type>);
 
struct Tree
{
Type value;
Tree* left;
Tree* right;
}
 
fn void Tree.replace_all(&self, Type new_value)
{
self.value = new_value;
if (self.left) self.left.replace_all(new_value);
if (self.right) self.right.replace_all(new_value);
}
</syntaxhighlight>
 
Usage:
<syntaxhighlight lang="c3">import tree;
 
fn void test()
{
Tree(<int>) inttree;
inttree.replace_all(3);
}</syntaxhighlight>
 
=={{header|Ceylon}}==
 
<langsyntaxhighlight lang="ceylon">class BinaryTree<Data>(shared Data data, shared BinaryTree<Data>? left = null, shared BinaryTree<Data>? right = null) {
shared BinaryTree<NewData> myMap<NewData>(NewData f(Data d)) =>
Line 253 ⟶ 278:
value tree2 = tree1.myMap((x) => x * 333.33);
tree2.myMap(print);
}</langsyntaxhighlight>
 
=={{header|Clean}}==
 
<langsyntaxhighlight 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)</langsyntaxhighlight>
 
<blockquote><small>
Line 268 ⟶ 293:
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'':
 
<langsyntaxhighlight 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)</langsyntaxhighlight>
 
<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:
 
<langsyntaxhighlight lang="clean">add1Everywhere :: (f a) -> (f a) | Functor f & Num a
add1Everywhere nums = fmap (\x = x + 1) nums</langsyntaxhighlight>
 
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>.
Line 286 ⟶ 311:
Common Lisp is not statically typed, but types can be defined which are parameterized over other types. In the following piece of code, a type <code>pair</code> is defined which accepts two (optional) type specifiers. An object is of type <code>(pair :car car-type :cdr cdr-type)</code> if an only if it is a cons whose car is of type <code>car-type</code> and whose cdr is of type <code>cdr-type</code>.
 
<langsyntaxhighlight lang="lisp">(deftype pair (&key (car 't) (cdr 't))
`(cons ,car ,cdr))</langsyntaxhighlight>
 
Example
Line 298 ⟶ 323:
 
=={{header|D}}==
<langsyntaxhighlight lang="d">class ArrayTree(T, uint N) {
T[N] data;
typeof(this) left, right;
Line 343 ⟶ 368:
//root.tmap(x => writefln("%(%.2f %)", x));
root.tmap((ref x) => writefln("%(%.2f %)", x));
}</langsyntaxhighlight>
{{out}}
<pre>1.00 1.00 1.00
Line 362 ⟶ 387:
 
=={{header|Dart}}==
<langsyntaxhighlight lang="dart">class TreeNode<T> {
T value;
Line 403 ⟶ 428:
print('second tree');
newRoot.forEach(print);
}</langsyntaxhighlight>
{{out}}
<pre>first tree
Line 424 ⟶ 449:
(Note: The guard definition is arguably messy boilerplate; future versions of E may provide a scheme where the <code>interface</code> expression can itself be used to describe parametricity, and message signatures using the type parameter, but this has not been implemented or fully designed yet. Currently, this example is more of “you can do it if you need to” than something worth doing for every data structure in your program.)
 
<langsyntaxhighlight lang="e">interface TreeAny guards TreeStamp {}
def Tree {
to get(Value) {
Line 454 ⟶ 479:
}
return tree
}</langsyntaxhighlight>
 
<langsyntaxhighlight lang="e">? def t := makeTree(int, 0, null, null)
# value: <tree>
 
Line 466 ⟶ 491:
 
? t :Tree[int]
# value: <tree></langsyntaxhighlight>
 
=={{header|F_Sharp|F#FreeBASIC}}==
{{trans|Visual Basic .NET}}
FreeBASIC does not support object-oriented programming, so we will use a more procedural approach.
<syntaxhighlight lang="vbnet">Type BinaryTree
valor As Integer
izda As BinaryTree Ptr
dcha As BinaryTree Ptr
End Type
 
Sub PrintTree(t As BinaryTree Ptr, depth As Integer)
<lang fsharp>
If t = 0 Then Exit Sub
Print String(depth, Chr(9)); t->valor
PrintTree(t->izda, depth + 1)
PrintTree(t->dcha, depth + 1)
End Sub
 
Dim As BinaryTree b = Type(6)
Dim As BinaryTree bLeft = Type(5)
Dim As BinaryTree bRight = Type(7)
b.izda = @bLeft
b.dcha = @bRight
 
PrintTree(@b, 0)</syntaxhighlight>
 
=={{header|F_Sharp|F#}}==
<syntaxhighlight lang="fsharp">
namespace RosettaCode
 
Line 480 ⟶ 528:
| Element(x) -> Element(f x)
| Tree(x,left,right) -> Tree((f x), left.Map(f), right.Map(f))
</syntaxhighlight>
</lang>
 
We can test this binary tree like so:
<langsyntaxhighlight lang="fsharp">
let t1 = Tree(2, Element(1), Tree(4,Element(3),Element(5)) )
let t2 = t1.Map(fun x -> x * 10)
</syntaxhighlight>
</lang>
 
=={{header|Fortran}}==
Fortran does not offer polymorphism by parameter type, which is to say, enables the same source code to be declared applicable for parameters of different types, so that a contained statement such as <code>X = A + B*C</code> would work for any combination of integer or floating-point or complex variables as actual parameters, since exactly that (source) code would be workable in every case. Further, there is no standardised pre-processor protocol whereby one could replicate such code to produce a separate subroutine or function specific to every combination.
 
However, with F90 came the MODULE protocol with facilities suitable for defining "generic" subroutines or functions, or so it appears: <langsyntaxhighlight Fortranlang="fortran"> MODULE SORTSEARCH !Genuflect towards Prof. D. Knuth.
 
INTERFACE FIND !Binary chop search, not indexed.
Line 525 ⟶ 573:
END FUNCTION FINDI4 !On success, THIS = NUMB(FINDI4); no fancy index here...
 
END MODULE SORTSEARCH </langsyntaxhighlight>
 
There would be a function (with a unique name) for each of the contemplated variations in parameter types, and when the compiler reached an invocation of FIND(...) it would select by matching amongst the combinations that had been defined in the routines named in the INTERFACE statement. The various actual functions could have different code, and in this case, only the <code>INTEGER*4 THIS,NUMB(1:*)</code> need be changed, say to <code>REAL*4 THIS,NUMB(1:*)</code> for FINDF4, which is why both variables are named in the one statement. However, for searching CHARACTER arrays, because the character comparison operations differ from those for numbers (and, no three-way IF-test either), additional changes are required. Thus, function FIND would appear to be a polymorphic function that accepts and returns a variety of types, but it is not, and indeed, there is actually no function called FIND anywhere in the compiled code.
Line 537 ⟶ 585:
But sometimes it is not so troublesome, as in [[Pathological_floating_point_problems#The_Chaotic_Bank_Society]] whereby the special EPSILON(x) function that reports on the precision of a nominated variable of type ''x'' is used to determine the point beyond which further calculation (in that precision, for that formula) will make no difference.
 
Having flexible facilities available my lead one astray. Consider the following data aggregate, as became available with F90: <langsyntaxhighlight Fortranlang="fortran"> TYPE STUFF
INTEGER CODE !A key number.
CHARACTER*6 NAME !Associated data.
INTEGER THIS !etc.
END TYPE STUFF
TYPE(STUFF) TABLE(600) !An array of such entries. </langsyntaxhighlight>
Suppose the array was in sorted order by each entry's value of CODE so that TABLE(1).CODE <= TABLE(2).CODE, etc. and one wished to find the index of an entry with a specific value, ''x'', of CODE. It is pleasing to be able to write <code>FIND(x,TABLE.CODE,N)</code> and have it accepted by the compiler. Rather less pleasing is that it runs very slowly.
 
Line 558 ⟶ 606:
 
Implementation of binaryTree and bTree is dummied, but you can see that implementation of average of binaryTree contains code specific to its representation (left, right) and that implementation of bTree contains code specific to its representation (buckets.)
<langsyntaxhighlight lang="go">package main
 
import "fmt"
Line 610 ⟶ 658:
visit(9)
}
}</langsyntaxhighlight>
Output:
<pre>
Line 618 ⟶ 666:
 
Alternatively, if generics are introduced into Go based on the current design, this is how the C++ example might look if translated to Go:
<langsyntaxhighlight lang="go">package rosettacode
 
type Tree(type T) struct {
Line 630 ⟶ 678:
if t.left != nil { t.left.ReplaceAll(rep) }
if t.right != nil { t.right.ReplaceAll(rep) }
}</langsyntaxhighlight>
 
=={{header|Groovy}}==
{{trans|Java}} (more or less)
Solution:
<langsyntaxhighlight lang="groovy">class Tree<T> {
T value
Tree<T> left
Line 651 ⟶ 699:
right?.replaceAll(value)
}
}</langsyntaxhighlight>
 
=={{header|Haskell}}==
 
<langsyntaxhighlight 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)</langsyntaxhighlight>
 
<blockquote><small>
Line 666 ⟶ 714:
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'':
 
<langsyntaxhighlight 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)</langsyntaxhighlight>
 
<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:
 
<langsyntaxhighlight lang="haskell">add1Everywhere :: (Functor f, Num a) => f a -> f a
add1Everywhere nums = fmap (\x -> x + 1) nums</langsyntaxhighlight>
 
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>.
Line 685 ⟶ 733:
of node. Note that the nodes do no even have to be of the same type.
 
<langsyntaxhighlight lang="unicon">procedure main()
bTree := [1, [2, [4, [7]], [5]], [3, [6, [8], [9]]]]
mapTree(bTree, write)
Line 694 ⟶ 742:
procedure mapTree(tree, f)
every f(\tree[1]) | mapTree(!tree[2:0], f)
end</langsyntaxhighlight>
 
=={{header|Inform 7}}==
Phrases (the equivalent of global functions) can be defined with type parameters:
<langsyntaxhighlight lang="inform7">Polymorphism is a room.
 
To find (V - K) in (L - list of values of kind K):
Line 710 ⟶ 758:
find "needle" in {"parrot", "needle", "rutabaga"};
find 6 in {2, 3, 4};
end the story.</langsyntaxhighlight>
 
Inform 7 does not allow user-defined parametric types. Some built-in types can be parameterized, though:
<langsyntaxhighlight lang="inform7">list of numbers
relation of texts to rooms
object based rulebook producing a number
Line 720 ⟶ 768:
number valued property
text valued table column
phrase (text, text) -> number</langsyntaxhighlight>
 
=={{header|J}}==
Line 732 ⟶ 780:
=={{header|Java}}==
Following the C++ example:
<langsyntaxhighlight lang="java">public class Tree<T>{
private T value;
private Tree<T> left;
Line 744 ⟶ 792:
right.replaceAll(value);
}
}</langsyntaxhighlight>
 
=={{header|Julia}}==
{{works with|Julia|1.3.16}}
 
<syntaxhighlight lang ="julia">mutable structmodule Tree{T}BinaryTrees
 
val::T
mutable struct BinaryTree{V}
lchild::Union{Tree{T}, Nothing}
v::V
rchild::Union{Tree{T}, Nothing}
l::Union{BinaryTree{V}, Nothing}
r::Union{BinaryTree{V}, Nothing}
end
 
TreeBinaryTree(v::T) where T = TreeBinaryTree(v, nothing, nothing) # Single arg constructor
 
map(f, bt::BinaryTree) = BinaryTree(f(bt.v), map(f, bt.l), map(f, bt.r))
map(f, bt::Nothing) = nothing
 
let inttree = BinaryTree(
"""
0,
Apply `f` (element-wise and in-place) to the values in tree `bt`.
BinaryTree(
Also prints the tree like an s-expression *for demonstrative purposes only*,
1,
new types should overload the `show()` function for pretty-printing.
BinaryTree(3),
"""
BinaryTree(5),
function map!(f::Function, bt::Tree{T}) where T
bt.val= f(bt.val ),
BinaryTree(
print(" (" * string(bt.val)) # Demonstration only
2,
bt.lchild !== nothing && map!(f, bt.lchild)
BinaryTree(4),
bt.rchild !== nothing && map!(f, bt.rchild)
nothing,
print(")") # Demonstration only
),
)
map(x -> 2x^2, inttree)
end
 
let strtree = BinaryTree(
function test_treemap()
inttree = Tree(0 "hello",
TreeBinaryTree(1,
Tree(3)"world!",
TreeBinaryTree(5)"Julia"),
Tree(2nothing,
Tree(4),
nothing))BinaryTree(
map!(x -> 2x^2, inttree) # Pass an anonymous function"foo",
# (0 (2 (18) (50)) (8 BinaryTree(32))"bar"),
BinaryTree("baz"),
println()
strtree = Tree("hello" ),
)
Tree("world!",
map(uppercase, strtree)
Tree("Julia"),
end
nothing),
 
Tree("foo",
end</syntaxhighlight>
Tree("bar"),
Tree("baz")))
map!(uppercase, strtree)
# (HELLO (WORLD! (JULIA)) (FOO (BAR) (BAZ)))
end</lang>
 
=={{header|Kotlin}}==
{{trans|C#}}
<langsyntaxhighlight lang="scala">// version 1.0.6
 
class BinaryTree<T>(var value: T) {
Line 817 ⟶ 869:
val b2 = b.map { it * 10.0 }
println(b2.showTopThree())
}</langsyntaxhighlight>
 
{{out}}
Line 824 ⟶ 876:
(50.0, 60.0, 70.0)
</pre>
 
=={{header|Mathematica}}/{{header|Wolfram Language}}==
The Wolfram language is naturally polymorphic. Function can (generally) accept any type. Here an example to join two lists of with different types and an example of squaring an input:
<syntaxhighlight lang="mathematica">f[a_] := Join[a, a]
f[{1, 2, 3}]
f[{"1", "2", "3"}]
f[{1.1, 2.1, 3.1}]
f[G[1, "a", Pi]]
g[x_] := x^2
g[2]
g[3.5]
g[Pi]
g["a"]</syntaxhighlight>
{{out}}
<pre>{1,2,3,1,2,3}
{1,2,3,1,2,3}
{1.1,2.1,3.1,1.1,2.1,3.1}
G[1,a,\[Pi],1,a,\[Pi]]
4
12.25
\[Pi]^2
(a)^2</pre>
 
=={{header|Mercury}}==
<langsyntaxhighlight lang="mercury">:- type tree(A) ---> empty ; node(A, tree(A), tree(A)).
 
:- func map(func(A) = B, tree(A)) = tree(B).
 
map(_, empty) = empty.
map(F, node(A, Left, Right)) = node(F(A), map(F, Left), map(F, Right)).</langsyntaxhighlight>
 
=={{header|Nim}}==
<langsyntaxhighlight lang="nim">import strutils, sugar
 
type Tree[T] = ref object
Line 881 ⟶ 955:
echo "Tree created by applying a function to each node:"
let tree1 = tree.map((x) => 1 / x)
print(tree1)</langsyntaxhighlight>
 
{{out}}
Line 905 ⟶ 979:
{{trans|C++}}
{{works with|Xcode|7}}
<langsyntaxhighlight lang="objc">@interface Tree<T> : NSObject {
T value;
Tree<T> *left;
Line 920 ⟶ 994:
[right replaceAll:v];
}
@end</langsyntaxhighlight>
Note that the generic type variable is only used in the declaration, but not in the implementation.
 
=={{header|OCaml}}==
 
<langsyntaxhighlight lang="ocaml">type 'a tree = Empty | Node of 'a * 'a tree * 'a tree
 
(** val map_tree : ('a -> 'b) -> 'a tree -> 'b tree *)
let rec map_tree f = function
| Empty -> Empty
| Node (x,l,r) -> Node (f x, map_tree f l, map_tree f r)</langsyntaxhighlight>
 
{{omit from|Oforth|Oforth is nt statically-typed language}}
Line 949 ⟶ 1,023:
Of course many builtin routines are naturally generic, such as sort and print.<br>
Most programming languages would throw a hissy fit if you tried to sort (or print) a mixed collection of strings and integers, but not Phix:
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>?sort(shuffle({5,"oranges",6,"apples",7}))</lang>
<span style="color: #0000FF;">?</span><span style="color: #7060A8;">sort</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">shuffle</span><span style="color: #0000FF;">({</span><span style="color: #000000;">5</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"oranges"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">6</span><span style="color: #0000FF;">,</span><span style="color: #008000;">"apples"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">7</span><span style="color: #0000FF;">}))</span>
<!--</syntaxhighlight>-->
{{out}}
<pre>
Line 961 ⟶ 1,037:
because lhs assignee!=rhs reference (aka root2!=root) in "root2 = tmap(root,rid)", not that such a "deep clone"
would (barring a few dirty low-level tricks) behave any differently to "root2=root", which is "a straightforward shared reference
with cow semantics". Aside: this example lost a little bit of it's charm when the deep_copy() had to go in to make it pwa/p2js compatible, which has somewhat negated the previous sentence, but that was happening implicitly anyway, and the depths of 1 (ie ",1" on the deep_copy()) retain similar efficiency.
with cow semantics".
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>enum data, left, right
<span style="color: #008080;">with</span> <span style="color: #008080;">javascript_semantics</span>
 
<span style="color: #008080;">enum</span> <span style="color: #000000;">data</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">left</span><span style="color: #0000FF;">,</span> <span style="color: #000000;">right</span>
function tmap(sequence tree, integer rid)
tree[data] = call_func(rid,{tree[data]})
if tree[left]!=null then tree[left] = tmap(tree[left],rid) end if
if tree[right]!=null then tree[right] = tmap(tree[right],rid) end if
return tree
end function
 
function newnode(object v)
return {v,null,null}
end function
<span style="color: #008080;">function</span> <span style="color: #000000;">tmap</span><span style="color: #0000FF;">(</span><span style="color: #004080;">sequence</span> <span style="color: #000000;">tree</span><span style="color: #0000FF;">,</span> <span style="color: #004080;">integer</span> <span style="color: #000000;">rid</span><span style="color: #0000FF;">)</span>
function add10(atom x) return x+10 end function
<span style="color: #000000;">tree</span><span style="color: #0000FF;">[</span><span style="color: #000000;">data</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">rid</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tree</span><span style="color: #0000FF;">[</span><span style="color: #000000;">data</span><span style="color: #0000FF;">])</span>
 
<span style="color: #008080;">if</span> <span style="color: #000000;">tree</span><span style="color: #0000FF;">[</span><span style="color: #000000;">left</span><span style="color: #0000FF;">]!=</span><span style="color: #004600;">null</span> <span style="color: #008080;">then</span> <span style="color: #000000;">tree</span><span style="color: #0000FF;">[</span><span style="color: #000000;">left</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tmap</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tree</span><span style="color: #0000FF;">[</span><span style="color: #000000;">left</span><span style="color: #0000FF;">],</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span><span style="color: #000000;">rid</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
procedure main()
<span style="color: #008080;">if</span> <span style="color: #000000;">tree</span><span style="color: #0000FF;">[</span><span style="color: #000000;">right</span><span style="color: #0000FF;">]!=</span><span style="color: #004600;">null</span> <span style="color: #008080;">then</span> <span style="color: #000000;">tree</span><span style="color: #0000FF;">[</span><span style="color: #000000;">right</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tmap</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">tree</span><span style="color: #0000FF;">[</span><span style="color: #000000;">right</span><span style="color: #0000FF;">],</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span><span style="color: #000000;">rid</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">end</span> <span style="color: #008080;">if</span>
object root = newnode(1.00)
<span style="color: #008080;">return</span> <span style="color: #000000;">tree</span>
-- Add some nodes.
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
root[left] = newnode(1.10)
root[left][left] = newnode(1.11)
root[left][right] = newnode(1.12)
<span style="color: #008080;">function</span> <span style="color: #000000;">newnode</span><span style="color: #0000FF;">(</span><span style="color: #004080;">object</span> <span style="color: #000000;">v</span><span style="color: #0000FF;">)</span>
root[right] = newnode(1.20)
<span style="color: #008080;">return</span> <span style="color: #0000FF;">{</span><span style="color: #000000;">v</span><span style="color: #0000FF;">,</span><span style="color: #004600;">null</span><span style="color: #0000FF;">,</span><span style="color: #004600;">null</span><span style="color: #0000FF;">}</span>
root[right][left] = newnode(1.21)
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
root[right][right] = newnode(1.22)
<span style="color: #008080;">function</span> <span style="color: #000000;">add10</span><span style="color: #0000FF;">(</span><span style="color: #004080;">atom</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">)</span> <span style="color: #008080;">return</span> <span style="color: #000000;">x</span><span style="color: #0000FF;">+</span><span style="color: #000000;">10</span> <span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<span style="color: #008080;">procedure</span> <span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
-- Now the tree has seven nodes.
<span style="color: #004080;">object</span> <span style="color: #000000;">root</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">newnode</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1.00</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- Add some nodes.</span>
<span style="color: #000000;">root</span><span style="color: #0000FF;">[</span><span style="color: #000000;">left</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">newnode</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1.10</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">root</span><span style="color: #0000FF;">[</span><span style="color: #000000;">left</span><span style="color: #0000FF;">][</span><span style="color: #000000;">left</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">newnode</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1.11</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">root</span><span style="color: #0000FF;">[</span><span style="color: #000000;">left</span><span style="color: #0000FF;">][</span><span style="color: #000000;">right</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">newnode</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1.12</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">root</span><span style="color: #0000FF;">[</span><span style="color: #000000;">right</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">newnode</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1.20</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">root</span><span style="color: #0000FF;">[</span><span style="color: #000000;">right</span><span style="color: #0000FF;">][</span><span style="color: #000000;">left</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">newnode</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1.21</span><span style="color: #0000FF;">)</span>
<span style="color: #000000;">root</span><span style="color: #0000FF;">[</span><span style="color: #000000;">right</span><span style="color: #0000FF;">][</span><span style="color: #000000;">right</span><span style="color: #0000FF;">]</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">newnode</span><span style="color: #0000FF;">(</span><span style="color: #000000;">1.22</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- Now the tree has seven nodes.
-- Show the whole tree.</span>
<span style="color: #7060A8;">ppOpt</span><span style="color: #0000FF;">({</span><span style="color: #004600;">pp_Nest</span><span style="color: #0000FF;">,</span><span style="color: #000000;">2</span><span style="color: #0000FF;">})</span>
<span style="color: #7060A8;">pp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">root</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- Modify the whole tree.</span>
<span style="color: #000000;">root</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tmap</span><span style="color: #0000FF;">(</span><span style="color: #000000;">root</span><span style="color: #0000FF;">,</span><span style="color: #000000;">add10</span><span style="color: #0000FF;">)</span>
<span style="color: #000080;font-style:italic;">-- ShowCreate thea whole new tree.</span>
<span style="color: #004080;">object</span> <span style="color: #000000;">root2</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">tmap</span><span style="color: #0000FF;">(</span><span style="color: #7060A8;">deep_copy</span><span style="color: #0000FF;">(</span><span style="color: #000000;">root</span><span style="color: #0000FF;">,</span><span style="color: #000000;">1</span><span style="color: #0000FF;">),</span><span style="color: #000000;">newnode</span><span style="color: #0000FF;">)</span>
ppOpt({pp_Nest,2})
pp(root)
<span style="color: #000080;font-style:italic;">-- ModifyShow the whole tree again.</span>
<span style="color: #7060A8;">pp</span><span style="color: #0000FF;">(</span><span style="color: #000000;">root</span><span style="color: #0000FF;">)</span>
root = tmap(root,routine_id("add10"))
<span style="color: #008080;">end</span> <span style="color: #008080;">procedure</span>
 
<span style="color: #000000;">main</span><span style="color: #0000FF;">()</span>
-- Create a whole new tree.
<!--</syntaxhighlight>-->
object root2 = tmap(root,rid)
 
-- Show the whole tree again.
pp(root)
end procedure
main()</lang>
{{out}}
<pre>
Line 1,024 ⟶ 1,103:
=={{header|PicoLisp}}==
PicoLisp is dynamically-typed, so in principle every function is polymetric over its arguments. It is up to the function to decide what to do with them. A function traversing a tree, modifying the nodes in-place (no matter what the type of the node is):
<langsyntaxhighlight PicoLisplang="picolisp">(de mapTree (Tree Fun)
(set Tree (Fun (car Tree)))
(and (cadr Tree) (mapTree @ Fun))
(and (cddr Tree) (mapTree @ Fun)) )</langsyntaxhighlight>
Test:
<pre style="height:20em;overflow:scroll">(balance 'MyTree (range 1 7)) # Create a tree of numbers
Line 1,083 ⟶ 1,162:
-> NIL</pre>
 
=={{header|RacketProlog}}==
{{works with|SWI Prolog}}
SWI-Prolog does not support object-oriented programming, but we can simulate it.
<syntaxhighlight lang="prolog">% Tree Definition
tree(leaf(_)).
tree(branch(Left, Right)) :- tree(Left), tree(Right).
 
% Definition of the addone function
Typed Racket has parametric polymorphism:
addone(X, Y) :- Y is X + 1.
 
% Definition of treewalk
<lang racket>
treewalk(leaf(Value), Func, leaf(NewValue)) :- call(Func, Value, NewValue).
treewalk(branch(Left, Right), Func, branch(NewLeft, NewRight)) :-
treewalk(Left, Func, NewLeft),
treewalk(Right, Func, NewRight).
 
% Execution
run :-
X = branch(leaf(2), branch(leaf(3),leaf(4))),
treewalk(X, addone, Y),
write(Y).</syntaxhighlight>
 
=={{header|Racket}}==
Typed Racket has parametric polymorphism:
<syntaxhighlight lang="racket">
#lang typed/racket
 
Line 1,108 ⟶ 1,207:
(tree-map add1 (Node 5 (Node 3 #f #f) #f))
(Node 6 (Node 4 #f #f) #f))
</syntaxhighlight>
</lang>
 
=={{header|Raku}}==
(formerly Perl 6)
{{works with|Rakudo|2020.08.1}}
<syntaxhighlight lang="raku" perl6line>role BinaryTree[::T] {
has T $.value;
has BinaryTree[T] $.left;
Line 1,132 ⟶ 1,231:
 
$it.replace-all(42);
say $it;</langsyntaxhighlight>
{{out}}
<pre>IntTree.new(value => 42, left => IntTree.new(value => 42, left => BinaryTree[T], right => BinaryTree[T]), right => IntTree.new(value => 42, left => BinaryTree[T], right => BinaryTree[T]))</pre>
Line 1,138 ⟶ 1,237:
=={{header|REXX}}==
This REXX programming example is modeled after the &nbsp; '''D''' &nbsp; example.
<langsyntaxhighlight lang="rexx">/*REXX program demonstrates (with displays) a method of parametric polymorphism. */
call newRoot 1.00, 3 /*new root, and also indicate 3 stems.*/
/* [↓] no need to label the stems. */
Line 1,169 ⟶ 1,268:
end /*j*/ /* [↑] caused by concatenation.*/
say /*show a blank line to separate outputs*/
return</langsyntaxhighlight>
{{out|output|text=&nbsp; when using the default input:}}
<pre>
Line 1,192 ⟶ 1,291:
 
=={{header|Rust}}==
<langsyntaxhighlight lang="rust">struct TreeNode<T> {
value: T,
left: Option<Box<TreeNode<T>>>,
Line 1,237 ⟶ 1,336:
let new_root = root.my_map(&|x| *x as f64 * 333.333f64);
new_root.my_map(&|x| { println!("{}" , x) });
}</langsyntaxhighlight>
 
=={{header|Scala}}==
Line 1,244 ⟶ 1,343:
the example in question:
 
<langsyntaxhighlight lang="scala">case class Tree[+A](value: A, left: Option[Tree[A]], right: Option[Tree[A]]) {
def map[B](f: A => B): Tree[B] =
Tree(f(value), left map (_.map(f)), right map (_.map(f)))
}</langsyntaxhighlight>
 
Note that the type parameter of the class <tt>Tree</tt>, <tt>[+A]</tt>. The
Line 1,253 ⟶ 1,352:
will be a subtype of <tt>Tree[Y]</tt> if <tt>X</tt> is a subtype of <tt>Y</tt>. For example:
 
<langsyntaxhighlight lang="scala">class Employee(val name: String)
class Manager(name: String) extends Employee(name)
 
val t = Tree(new Manager("PHB"), None, None)
val t2: Tree[Employee] = t</langsyntaxhighlight>
 
The second assignment is legal because <tt>t</tt> is of type <tt>Tree[Manager]</tt>, and since
Line 1,265 ⟶ 1,364:
Another possible variance is the ''contra-variance''. For instance, consider the following example:
 
<langsyntaxhighlight lang="scala">def toName(e: Employee) = e.name
val treeOfNames = t.map(toName)</langsyntaxhighlight>
 
This works, even though <tt>map</tt> is expecting a function from <tt>Manager</tt> into something,
Line 1,273 ⟶ 1,372:
definition in Scala:
 
<langsyntaxhighlight lang="scala">trait Function1[-T1, +R]</langsyntaxhighlight>
 
The minus sign indicates that this trait is ''contra-variant'' in <tt>T1</tt>, which happens to be
Line 1,284 ⟶ 1,383:
Let's add another method to <tt>Tree</tt> to see another concept:
 
<langsyntaxhighlight lang="scala">case class Tree[+A](value: A, left: Option[Tree[A]], right: Option[Tree[A]]) {
def map[B](f: A => B): Tree[B] =
Tree(f(value), left map (_.map(f)), right map (_.map(f)))
def find[B >: A](what: B): Boolean =
(value == what) || left.map(_.find(what)).getOrElse(false) || right.map(_.find(what)).getOrElse(false)
}</langsyntaxhighlight>
 
The type parameter of <tt>find</tt> is <tt>[B >: A]</tt>. That means the type is some <tt>B</tt>, as long
Line 1,295 ⟶ 1,394:
accept it. To understand why, let's consider the following code:
 
<langsyntaxhighlight lang="scala">if (t2.find(new Employee("Dilbert")))
println("Call Catbert!")</langsyntaxhighlight>
 
Here we have <tt>find</tt> receiving an argument of type <tt>Employee</tt>, even though the tree
Line 1,307 ⟶ 1,406:
to be defined when a class is inherited. One simple example would be:
 
<langsyntaxhighlight lang="scala">trait DFA {
type Element
val map = new collection.mutable.HashMap[Element, DFA]()
}</langsyntaxhighlight>
 
A concrete class wishing to inherit from <tt>DFA</tt> would need to define <tt>Element</tt>. Abstract
Line 1,325 ⟶ 1,424:
When ''map'' is called ''aVariable'' is used also in the actual parameter of ''aFunc'': map(container1, num, num + 1)
 
<langsyntaxhighlight lang="seed7">$ include "seed7_05.s7i";
 
const func type: container (in type: elemType) is func
Line 1,361 ⟶ 1,460:
end for;
writeln;
end func;</langsyntaxhighlight>
 
Output:
Line 1,369 ⟶ 1,468:
 
=={{header|Standard ML}}==
<langsyntaxhighlight lang="sml">datatype 'a tree = Empty | Node of 'a * 'a tree * 'a tree
 
(** val map_tree = fn : ('a -> 'b) -> 'a tree -> 'b tree *)
fun map_tree f Empty = Empty
| map_tree f (Node (x,l,r)) = Node (f x, map_tree f l, map_tree f r)</langsyntaxhighlight>
 
=={{header|Swift}}==
{{trans|Java}}
<langsyntaxhighlight lang="swift">class Tree<T> {
var value: T?
var left: Tree<T>?
Line 1,387 ⟶ 1,486:
right?.replaceAll(value)
}
}</langsyntaxhighlight>
 
Another version based on Algebraic Data Types:
{{works with|Swift|2+}}
<langsyntaxhighlight lang="swift">enum Tree<T> {
case Empty
indirect case Node(T, Tree<T>, Tree<T>)
Line 1,401 ⟶ 1,500:
}
}
}</langsyntaxhighlight>
 
=={{header|Ursala}}==
Line 1,407 ⟶ 1,506:
routinely. A parameterized binary tree type can be defined using a syntax for anonymous
recursion in type expressions as in this example,
<langsyntaxhighlight Ursalalang="ursala">binary_tree_of "node-type" = "node-type"%hhhhWZAZ</langsyntaxhighlight>
or by way of a recurrence solved using a fixed point combinator imported from a library
as shown below.
<langsyntaxhighlight Ursalalang="ursala">#import tag
 
#fix general_type_fixer 1
 
binary_tree_of "node-type" = ("node-type",(binary_tree_of "node-type")%Z)%drWZwlwAZ</langsyntaxhighlight>
(The <code>%Z</code> type operator constructs a "maybe" type, i.e., the free union of its operand type
with the null value. Others shown above are standard stack manipulation primitives, e.g. <code>d</code> (dup) and <code>w</code> (swap), used to build the type expression tree.) At the other extreme, one may construct an equivalent parameterized type in
point-free form.
<langsyntaxhighlight Ursalalang="ursala">binary_tree_of = %-hhhhWZAZ</langsyntaxhighlight>
A mapping combinator over this type can be defined with pattern matching like this
<langsyntaxhighlight Ursalalang="ursala">binary_tree_map "f" = ~&a^& ^A/"f"@an ~&amPfamPWB</langsyntaxhighlight>
or in point free form like this.
<langsyntaxhighlight Ursalalang="ursala">binary_tree_map = ~&a^&+ ^A\~&amPfamPWB+ @an</langsyntaxhighlight>
Here is a test program
defining a type of binary trees of strings, and a function that concatenates each node
with itself.
<langsyntaxhighlight Ursalalang="ursala">string_tree = binary_tree_of %s
 
x = 'foo': ('bar': (),'baz': ())
Line 1,432 ⟶ 1,531:
#cast string_tree
 
example = (binary_tree_map "s". "s"--"s") x</langsyntaxhighlight>
Type signatures are not necessarily associated with function declarations, but
have uses in the other contexts such as assertions and compiler directives
Line 1,442 ⟶ 1,541:
=={{header|Visual Basic .NET}}==
{{trans|C# modern version}}
<langsyntaxhighlight lang="vbnet">Class BinaryTree(Of T)
ReadOnly Property Left As BinaryTree(Of T)
ReadOnly Property Right As BinaryTree(Of T)
Line 1,479 ⟶ 1,578:
Console.WriteLine(b2)
End Sub
End Module</langsyntaxhighlight>
{{out}}
<pre>6
Line 1,490 ⟶ 1,589:
 
=={{header|Visual Prolog}}==
<langsyntaxhighlight lang="prolog">
domains
tree{Type} = branch(tree{Type} Left, tree{Type} Right); leaf(Type Value).
Line 1,510 ⟶ 1,609:
write(Y),
succeed().
</syntaxhighlight>
</lang>
 
=={{header|Wren}}==
Line 1,519 ⟶ 1,618:
 
Fortunately, we can simulate PP by passing an extra parameter to a collection class's contructor to specify the type of values to be used for that particular instantiation. We can then use this to guard against the wrong type of values being passed to the class's other methods.
<langsyntaxhighlight ecmascriptlang="wren">class BinaryTree {
construct new(T, value) {
if (!(T is Class)) Fiber.abort ("T must be a class.")
Line 1,571 ⟶ 1,670:
var b2 = b.map{ |i| i * 10 }
System.print(b2.showTopThree())
b2.value = "six" // generates an error because "six" is not a Num</langsyntaxhighlight>
 
{{out}}
2,122

edits