Skip to content

Instantly share code, notes, and snippets.

@natefaubion
Created May 30, 2013 04:03
Show Gist options
  • Save natefaubion/5675656 to your computer and use it in GitHub Desktop.
Save natefaubion/5675656 to your computer and use it in GitHub Desktop.
Parameterized data types using adt.js
{data, any, only} = require 'adt'
# List definition using `any`. While we can restrict the tail to be a only List types,
# we can't restrict the head to be a specific type.
List = data ->
Nil: null
Cons:
head: any
tail: only this
List::map = (fn) ->
return this if @isNil
List.Cons fn(@head), @tail.map(fn)
mixed = List.Cons(1, List.Cons('a', List.Nil))
# Bork
mixed.map (x) -> x * 2
# Using https://github.com/natefaubion/adt.js/tree/paramaterized
{construct, only} = require 'adt'
# Declare List as a type constructor
List = construct (A) ->
Nil: null
Cons:
head: only A
tail: only List(A)
# We can use `set` since we don't have easy access to the constructors.
List::map = (fn) ->
return this if @isNil
@set
head: fn(@head)
tail: @tail.map(fn)
# Create lists of Numbers
{Cons, Nil} = List(Number)
# TypeError
mixed = Cons(1, Cons('2', Cons(3, Nil)))
# OK
list = Cons(1, Cons(2, Cons(3, Nil)))
# -> "Cons(2, Cons(4, Cons(6, Nil)))"
list.map((x) -> x * 2).toString()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment