Parametric polymorphism: Difference between revisions

From Rosetta Code
Content added Content deleted
(added standard ml)
m (lang tags)
Line 40: Line 40:
=={{header|C++}}==
=={{header|C++}}==


template<class T>
<lang cpp> template<class T>
class tree
class tree
{
{
Line 48: Line 48:
public:
public:
void replace_all (T new_value);
void replace_all (T new_value);
};
};</lang>


For simplicity, we replace all values in the tree with a new value:
For simplicity, we replace all values in the tree with a new value:


template<class T>
<lang cpp> template<class T>
void tree<T>::replace_all (T new_value)
void tree<T>::replace_all (T new_value)
{
{
Line 58: Line 58:
left->replace_all (new_value);
left->replace_all (new_value);
right->replace_all (new_value);
right->replace_all (new_value);
}
}</lang>
=={{header|D}}==
=={{header|D}}==
D template can parametric by constant.
D template can parametric by constant.
<pre>module parapoly ;
<lang d>module parapoly ;


class ArrayTree(T, int LEN) {
class ArrayTree(T, int LEN) {
Line 75: Line 75:
if(RHS) RHS.map(dg) ;
if(RHS) RHS.map(dg) ;
}
}
}</pre>
}</lang>
This is a using example.
This is a using example.
<pre>
<lang d>
module polytest ;
module polytest ;
import std.stdio ;
import std.stdio ;
import parapoly ;
import parapoly ;

</pre>
<pre style="background-color:#ffe">
//Instantiating an ArrayTree class of real(T) array, whose length(LEN) is 3.
//Instantiating an ArrayTree class of real(T) array, whose length(LEN) is 3.
alias ArrayTree!(real, 3) VecT ;
alias ArrayTree!(real, 3) VecT ;

</pre>
<pre>
void main() {
void main() {
VecT v = new VecT(0.01);
VecT v = new VecT(0.01);
Line 99: Line 97:
writefln() ;
writefln() ;
v.map((real[] x){writefln(x) ;} ) ;
v.map((real[] x){writefln(x) ;} ) ;
}</pre>
}</lang>
=={{header|Haskell}}==
=={{header|Haskell}}==


data Tree a = Empty | Node a (Tree a) (Tree a)
<lang haskell> data Tree a = Empty | Node a (Tree a) (Tree a)


mapTree :: (a -> b) -> Tree a -> Tree b
mapTree :: (a -> b) -> Tree a -> Tree b
mapTree f Empty = Empty
mapTree f Empty = Empty
mapTree f (Node x l r) = Node (f x) (mapTree f l) (mapTree f r)
mapTree f (Node x l r) = Node (f x) (mapTree f l) (mapTree f r)</lang>


=={{header|Java}}==
=={{header|Java}}==
Following the C++ example:
Following the C++ example:
public class Tree<T>{
<lang java> public class Tree<T>{
private T value;
private T value;
private Tree<T> left;
private Tree<T> left;
Line 122: Line 120:
right.replaceAll(value);
right.replaceAll(value);
}
}
}
}</lang>


=={{header|OCaml}}==
=={{header|OCaml}}==


type 'a tree = Empty | Node of 'a * 'a tree * 'a tree
<lang ocaml> type 'a tree = Empty | Node of 'a * 'a tree * 'a tree


(** val map_tree : ('a -> 'b) -> 'a tree -> 'b tree *)
(** val map_tree : ('a -> 'b) -> 'a tree -> 'b tree *)
let rec map_tree f = function
let rec map_tree f = function
| Empty -> Empty
| Empty -> Empty
| Node (x,l,r) -> Node (f x, map_tree f l, map_tree f r)
| Node (x,l,r) -> Node (f x, map_tree f l, map_tree f r)</lang>


=={{header|Standard ML}}==
=={{header|Standard ML}}==


datatype 'a tree = Empty | Node of 'a * 'a tree * 'a tree
<lang sml> datatype 'a tree = Empty | Node of 'a * 'a tree * 'a tree


(** val map_tree = fn : ('a -> 'b) -> 'a tree -> 'b tree *)
(** val map_tree = fn : ('a -> 'b) -> 'a tree -> 'b tree *)
fun map_tree f Empty = Empty
fun map_tree f Empty = Empty
| map_tree f (Node (x,l,r)) = Node (f x, map_tree f l, map_tree f r)
| map_tree f (Node (x,l,r)) = Node (f x, map_tree f l, map_tree f r)</lang>

Revision as of 17:50, 28 April 2009

Task
Parametric polymorphism
You are encouraged to solve this task according to the task description, using any language you may know.

Parametric Polymorphism is a way to define types or functions that are generic over other types. The genericity can be expressed by using type variables for the parameter type, and by a mechanism to explicitly or implicitly replace the type variables with concrete types when necessary.

Write a small example for a type declaration that is parametric over another type, together with a short bit of code (and its type signature) that uses it. A good example is a container type, let's say a binary tree, together with some function that traverses the tree, say, a map-function that operates on every element of the tree.

This language feature only applies to statically-typed languages.

Ada

<lang ada>

generic
   type Element_Type is private;
package Container is
   type Tree is tagged private;
   procedure Replace_All(The_Tree : in out Tree; New_Value : Element_Type);
private
   type Node;
   type Node_Access is access Node;
   type Tree tagged record
      Value : Element_type;
      Left  : Node_Access := null;
      Right : Node_Access := null;
   end record;
end Container;

</lang> <lang ada>

package body Container is
   procedure Replace_All(The_Tree : in out Tree; New_Value : Element_Type) is
   begin
      The_Tree.Value := New_Value;
      If The_Tree.Left /= null then
         The_Tree.Left.all.Replace_All(New_Value);
      end if;
      if The_tree.Right /= null then
         The_Tree.Right.all.Replace_All(New_Value);
      end if;
   end Replace_All;
end Container;

</lang>

C++

<lang cpp> template<class T>

class tree
{
  T value;
  tree *left;
  tree *right;
public:
  void replace_all (T new_value);
};</lang>

For simplicity, we replace all values in the tree with a new value:

<lang cpp> template<class T>

void tree<T>::replace_all (T new_value)
{
  value = new_value;
  left->replace_all (new_value);
  right->replace_all (new_value);
}</lang>

D

D template can parametric by constant. <lang d>module parapoly ;

class ArrayTree(T, int LEN) {

 // template instantiation in alias
 alias ArrayTree!(T, LEN) ANode ;  
 const int length = LEN ;
 T[LEN] array ;
 ANode LHS, RHS ;
 this (T initvalue) { array[] = initvalue ; }
 void map(void delegate(T[]) dg) { 
   dg(array) ;
   if(LHS) LHS.map(dg) ; 
   if(RHS) RHS.map(dg) ; 
 } 

}</lang> This is a using example. <lang d> module polytest ; import std.stdio ; import parapoly ;

//Instantiating an ArrayTree class of real(T) array, whose length(LEN) is 3. alias ArrayTree!(real, 3) VecT ;

void main() {

 VecT v = new VecT(0.01);
 // init an array tree.
 v.LHS = new VecT(1.11) ; v.LHS.LHS = new VecT(1.11) ; v.LHS.RHS = new VecT(1.12) ;
 v.RHS = new VecT(1.21) ; v.RHS.LHS = new VecT(1.21) ; v.RHS.RHS = new VecT(1.22) ;
 // do something start from root v
 v.map((real[] x){writefln(x) ;} ) ;
 real new_value = 0.9L ; 
 v.map((real[] x){x[] = new_value ;} ) ;
 writefln() ;
 v.map((real[] x){writefln(x) ;} ) ;

}</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>

Java

Following the C++ example: <lang java> public class Tree<T>{

	private T value;
	private Tree<T> left;
	private Tree<T> right;

	public void replaceAll(T value){
		this.value = value;
		if(left != null)
			left.replaceAll(value);
		if(right != null)
			right.replaceAll(value);
	}
}</lang>

OCaml

<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)</lang>

Standard ML

<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)</lang>