Exploring ReasonML 学习笔记 -- 3. Variant Types

174 阅读1分钟

Exploring ReasonML

  1. Variants as data structures
type point = Point(float, float);
type shape =
  | Rectangle(point, point)
  | Circle(point, float);

let bottomLeft = Point(-1.0, -2.0);
let topRight = Point(7.0, 6.0);

Pattern Matching

let computeArea = (s: shape) =>
  switch s {
  | Rectangle(Point(x1, y1), Point(x2, y2)) =>
    let width = abs_float(x2 -. x1);
    let height = abs_float(y2 -. y1);
    width *. height;
  | Circle(_, radius) => pi *. (radius ** 2.0)
  };
  1. Self-recursive data structures via variants
type intTree =
  | Empty
  | Node(int, intTree, intTree);

let rec computeSum = (t: intTree) =>
  switch t {
  | Empty => 0
  | Node(i, leftTree, rightTree) =>
    i + computeSum(leftTree) + computeSum(rightTree)
  };
  1. Mutually recursive data structures via variants
type intTree =
  | Empty
  | IntTreeNode(intNode)
and intNode =
  | IntNode(int, intTree, intTree);
  1. Parameterized variants
type tree('a) =
  | Empty
  | Node('a, tree('a), tree('a));
  1. Useful standard variants
type option('a) =
  | None
  | Some('a);
type result('good, 'bad) =
  | Ok('good)
  | Error('bad);

Example

type expression =
  | Plus(expression, expression)
  | Minus(expression, expression)
  | Times(expression, expression)
  | DividedBy(expression, expression)
  | Literal(int);

/* (3 - (16 / (6 + 2)) */
let expr =
  Minus(
    Literal(3),
    DividedBy(
      Literal(16),
      Plus(
        Literal(6),
        Literal(2)
      )
    )
  );

let rec eval(e: expression) =
  switch e {
  | Plus(e1, e2) => eval(e1) + eval(e2)
  | Minus(e1, e2) => eval(e1) - eval(e2)
  | Times(e1, e2) => eval(e1) * eval(e2)
  | DividedBy(e1, e2) => eval(e1) / eval(e2)
  | Literal(i) => i
  };