Examples

From UxADT
Jump to: navigation, search

This page contains short examples illustrating how the UxADT libraries can be used within each of the languages and platforms that do not provide native support for algebraic data types.

Haskell

As Haskell already provides native support for algebraic data types, the purpose of the Haskell UxADT library is to provide easy conversion between a native Haskell representation of a data type value, and a portable UxADT representation. Thus, the Haskell library is provided primarily as an interface between Haskell and the other supported languages and platforms. Currently, recursive, mutually recursive, and non-recursive monomorphic types are supported. For example, suppose the following two data type definitions are provided.

data Color =
    Red
  | Blue
  deriving (Typeable, Data, Show, Eq)
 
data Tree =
    Node Tree Tree
  | Leaf Color
  deriving (Typeable, Data, Show, Eq)

Automated conversion between the following two representations of a value is supported:

colorTy = dataTypeOf (Red)
treeTy = dataTypeOf (Leaf Red)
 
hs = Node (Leaf Red) (Node (Leaf Blue) (Leaf Red))
ux = C "Node" [C "Leaf" [C "Red" []], C "Node" [C "Leaf" [C "Blue" []], C "Leaf" [C "Red" []]]]

In the above, we would have that (uxadt hs) == (fromUxADT [colorTy, treeTy] ux :: Tree). Note that all the monomorphic types for which constructors might be found in the UxADT representation of the value must be supplied, or a runtime error will occur.

The Haskell library also provides automated conversion between the UxADT representation and a JSON representation via a class instance declaration (i.e., the UxADT type is a member of the JSON type class).

JavaScript

It is possible to use the library within a Node.js module in the following way.

  var uxadt = require("./uxadt.js");

It is possible to use the library within an HTML page in the following way.

  <script src="uxadt.js"></script>

You may want to define _ for the sake of concision. It does not matter what is assigned to _, as long as it is not a UxADT value.

  var _ = null;

The following is a simple algebraic data type definition in JavaScript using UxADT.

  uxadt._({
      Node: [_, _],
      Leaf: []
    });

To better document the implicit constraints associated with the definition, it is possible to provide an explicit name for the algebraic data type and the types of the constructor arguments. However, no static or dynamic checking of the constraints implied by this information is currently supported by the library itself.

  uxadt._('Tree', {
      Node: ['Tree', 'Tree'],
      Leaf: []
    });

An individual value can then be built up as an expression in the following way:

  Node(Node(Leaf(), Leaf()), Leaf())

Below is a simple recursive function that counts the number of nodes in a tree value (that corresponds to the algebraic data type definition in the above example).

  function size(t) {
    return t
      ._(Leaf(),     function()    { return 1; })
      ._(Node(_, _), function(x, y){ return 1 + size(x) + size(y); })
      .end;

The JavaScript library provides an alternate interface for using pattern matching on UxADT values in code that follows a more imperative paradigm. Note that the example below uses destructuring assignment (it is still possible to use the ._() method for simple boolean matching in earlier versions of JavaScript).

  function size(t) {
    if (t._(Leaf())) {
      return 1;
    } else if (t._(Node(_, _))) {
      [x, y] = t.matched();
      return 1 + size(x) + size(y);
    }
  }

PHP

To use the library, simply include the module. You may want to define _ as a global for the sake of concision. It does not matter what is assigned to _, as long as it is not a UxADT value.

  include 'uxadt.php';
  define('_', null);

The following is a simple algebraic data type definition in PHP using UxADT (notice that the module uses the new namespaces feature in PHP 5.3.0 and higher).

  \uxadt\_(array(
      'Node' => array(_, _),
      'Leaf' => array()
    ));

To better document the implicit constraints associated with the definition, it is possible to provide an explicit name for the algebraic data type and the types of the constructor arguments. However, no static or dynamic checking of the constraints implied by this information is currently supported by the library itself.

  \uxadt\_('Tree', array(
      'Node' => array('Tree', 'Tree'),
      'Leaf' => array()
    ));

An individual value can then be built up as an expression in the following way:

  Node(Node(Leaf(), Leaf()), Leaf())

Below is a simple recursive function that counts the number of nodes in a tree value (that corresponds to the algebraic data type definition in the above example).

  function size($t) {
    return $t
      ->_(Leaf(),     function()       { return 1; })
      ->_(Node(_, _), function($x, $y) { return 1 + size($x) + size($y); })
      ->end;
  }

The PHP library provides an alternate interface for using pattern matching on UxADT values in code that follows a more imperative paradigm.

  function size($t) {
    if ($t->_(Leaf())) {
      return 1;
    } else if ($t->_(Node(_, _))) {
      list($x, $y) = $t();
      return 1 + size($x) + size($y);
    }
  }

Python

To use the library, simply import the module. You may want to define _ as a global for the sake of concision. It does not matter what is assigned to _, as long as it is not a UxADT value.

  import uxadt
  _ = None

The following is a simple algebraic data type definition in Python using UxADT.

  uxadt._({\
      'Node': [_, _],\
      'Leaf': []\
    })

To better document the implicit constraints associated with the definition, it is possible to provide an explicit name for the algebraic data type and the types of the constructor arguments. However, no static or dynamic checking of the constraints implied by this information is currently supported by the library itself.

  uxadt._('Tree', {\
      'Node': ['Tree', 'Tree'],\
      'Leaf': []\
    })

An individual value can be built up as an expression in the following way:

  Node(Node(Leaf(), Leaf()), Leaf())

Below is a simple recursive function that counts the number of nodes in a tree value (that corresponds to the algebraic data type definition in the above example).

  def size(t):
    return t\
      ._(Leaf(),     lambda:     1)\
      ._(Node(_, _), lambda x,y: 1 + size(x) + size(y))\
      .end

The Python library provides an alternate interface for using pattern matching on UxADT values in code that follows a more imperative paradigm. This is particularly useful in Python because the body of a lambda expression cannot be a statement.

  def size(t):
    if t < Leaf():
      return 1
    elif t < Node(_, _):
      (x, y) = t
      return 1 + size(x) + size(y)