Roy
types
Who needs types after TDD?
JS[LH]int?
α → α
function(a) {
  return a;
}

Simon Peyton-Jones

"Types are, the world's
most used formal method,
by... 6 orders of magnitude..."
functional
Completely immutable

Warning

not production quality
let hundred = 100 
var hundred = 100;
console.log "Hello World"  
console.log("Hello World");
  1. weak typing
  2. duck typing
  3. monkey patching
  4. callback hell
  5. modules

problem #1

weak typing
// Won't compile
// console.log ("Hello" + 2)
let f x : Number = x


console.log (f 100)
// Won't compile:
// console.log (f "100")
var f = function(x) {
    return x;
};
console.log(f(100));
// Won't compile:
// console.log (f "100")

problem #2

duck typing
function show(a) {
    return a.name +
      ' sounds like: ' + a.sound;
}
show({
  name: 'Duck',
  sound: 'quack'
});
show({
  name: 'Hand',
  sound: 'clap'
});
show({
  name: 'Tree'
}); // Whoops!

structural types

let show a = a.name ++ ' sounds like: ' ++ a.sound
show {
  name: 'Duck'
  sound: 'quack'
}
show {
  name: 'Hand'
  sound: 'clap'
}
// Won't compile
// show {
//   name: 'Tree'
// }

sum types

data Option a =
  Some a | None
var Some = function(a_0) {
    if(!(this instanceof Some)) {
        return new Some(a_0);
    }
    this._0 = a_0;
};
var None = function() {
    if(!(this instanceof None)) {
        return new None();
    }
};

pattern matching

let noneZero o = match o      
  case (Some s) = s
  case (None ()) = 0
var noneZero = function(o) {
    return (function() {
        if(o instanceof Some) {
            var s = o._0;
            return s;
        } else if(o instanceof None) {    
            return 0;
        }
    })();
}
noneZero (None ())
// 0
noneZero (Some 1)
// 1
noneZero(None());
// 0
noneZero(Some(1));
// 1

problem #3

monkey patching
// ES6
String.prototype.contains = function(string, index) {
  return this.indexOf(string, index || 0) != -1;
};
// Mootools
String.prototype.contains = function(string, separator){
  return (separator)
    ? (separator + this + separator).indexOf(separator + string + separator) > -1
    : String(this).indexOf(string) > -1;
};
'Brian1Ben'.contains('Brian', 1) // ???
typeclass WithContains #a {
  contains: Function(String, String, #a, Boolean)
}

instance indexContains = WithContains Number {
  contains = indexOf
}

instance separatorContains = WithContains String {
  contains = \haystack needle sep ->
    (indexOf (splitBy haystack sep) needle) != -1
}

contains "Brian1Ben" "Brian" 1 // false
contains "Brian1Ben" "Brian" "1" // true
var indexContains = {
  contains: indexOf
};
var separatorContains = {
  contains: function(haystack, needle, sep) {
    return indexOf(splitBy(haystack, sep), needle) != -1;
  }
};
indexContains.contains("Brian1Ben", "Brian", 1); // false
separatorContains.contains("Brian1Ben", "Brian", "1"); // true

problem #4

callback hell
Escaping
Callback Hell
with monad syntax
app.get('/index', function(req, res, next) {
    User.get(req.params.userId, function(err, user) {
        if(err) return next(err);
        db.find({user: user.name}, function(err, cursor) {
            if(err) return next(err);
            cursor.toArray(function(err, items) {
                if(err) return next(err);
                res.send(items);
            });
        });
    });
});
let deferred = {
  return: \x ->
    let d = $.Deferred ()
    d.resolve x
    d.promise ()
  bind: \x f -> x.pipe f
}
var deferred = {
    "return": function(x) {
        var d = $.Deferred();
        d.resolve(x);
        return d.promise();
    },
    "bind": function(x, f) {
        return x.pipe(f);
    }
};
let v = do deferred
  val <- $.ajax 'examples/helloworld.roy'
  val2 <- $.ajax 'examples/alias.roy'
  return (val ++ val2)
var v = (function(){
    return deferred.bind($.ajax('examples/helloworld.roy'), function(val) {
        return deferred.bind($.ajax('examples/alias.roy'), function(val2) {
            return deferred.return(val + val2);
        });
    });
})();

problem #5

modules
compile to
 all the 
module standards?!

Roy write-once module

import "./settings"

let appName = "App " ++ settings.name
export appName

Browser global object

(function() {
// Using browser module: "settings"
var appName = "App " + settings.name;
this["appName"] = appName;
})();

CommonJS 1.0 (node.js)

var settings = require("./settings");
var appName = "App " + settings.name;
exports["appName"] = appName;

Async module defs

define('mymodule', ['settings'],
  function(requre, exports, settings) {
    var appName = "App " + settings.name;
    exports["appName"] = appName;    
  }
);
  1. weak typing
  2. duck typing
  3. monkey patching
  4. callback hell
  5. modules
implementation
gll.js (maybe)
1 - 2 - 3
(1 - 2) - 3 = -4
1 - (2 - 3) =  2
var S = gll.makeParser(function() {
    return gll.alt(
        gll.string("b"),
        gll.seq(S, S),
        gll.seq(S, S, S)
    );
});
escodegen (soon)
return "(function() {\n" + getIndent(1) +
  cases.join(" else ") + "\n" + getIndent() + "})()";
return {
  type: "CallExpression",
  callee: {
    type: "FunctionExpression",
    body: ...
  }
};
Brushtail
function count(from, to) {
    if(from >= to)
        return from;
    return count(from + 1, to);
}
function count(from, to) {
    var __tcor;
    tco:
        while (true) {
            if (from >= to) {
                __tcor = from;
                break tco;
            }
            {
                var __from = from + 1, __to = to;
                from = __from;
                to = __to;
                continue tco;
            }
        }
    return __tcor;
}
bilby.js
// Ad-hoc polymorphism
var extended = λ
  .method(
    "negate",
    function(b) {
      return typeof b == "boolean";
    },
    function(b) {
      return !b;
    }
  );
// Ad-hoc polymorphism
var extended2 = extended
  .method(
    "negate",
    function(n) {
      return typeof n == "number";  
    },
    function(n) {
      return -n;
    }
  );
// List
var List = λ.objectUnion(function(define) {
    return {
        Cons: define("car", "cdr"),
        Nil: define()
    };
});
List.Cons(1, List.Cons(2, List.Nil()));
// Monad syntax
λ.Do()(
  λ.some(1) >= function(x) {
    return x < 0 ? λ.none : λ.some(x + 2);
  }
).getOrElse(0) == 3;
// Property based tests
λ.forAll(
  function(n) {
    return n + n == 2 * n;
  },
  [Number]
).fold(
  function(fail) {
    return "Failed after " + fail.tries +
      " tries: " + fail.inputs.toString();
  },
  "All tests passed!"
);
emu.js
echo "
/**
  # Header

  Documentation
**/
ignored;" | emu
# Header

Documentation
roy.brianmckenna.org
Thanks!
@puffnfresh