Skip to content

Instantly share code, notes, and snippets.

@gaku-sei
Last active February 10, 2020 13:06
Show Gist options
  • Save gaku-sei/fe7e6375d4bd16c5b8574b6ddbea25a6 to your computer and use it in GitHub Desktop.
Save gaku-sei/fe7e6375d4bd16c5b8574b6ddbea25a6 to your computer and use it in GitHub Desktop.
Uses Immutable Array with bs-abstract to compile on BuckleScript 7.1.0
// Interfaces
module type FUNCTOR = {
type t('a);
let map: ('a => 'b, t('a)) => t('b);
};
module type ALT = {
include FUNCTOR;
let alt: (t('a), t('a)) => t('a);
};
module type PLUS = {
include ALT;
let empty: t('a);
};
// Immutable Array
module ImmutableArray = {
type t(+'a); // = array('a)
// Some magic first
// The type t above is a strict alias to the array type and they can be converter "blindly"
// Using a constructor, even unboxed, would not compile
external from: array('a) => t('a) = "%identity";
external to_: t('a) => array('a) = "%identity";
// This version of push is immutable and uses concat under the hood
let push: type a. (a, t(a)) => t(a) =
(x, xs) => xs |> to_ |> Js.Array.concat([|x|]) |> from;
// More functions...
};
// Implementations
module Functor: FUNCTOR with type t('a) = ImmutableArray.t('a) = {
type t('a) = ImmutableArray.t('a);
let map = (f, xs) => ImmutableArray.(xs |> to_ |> Js.Array.map(f) |> from);
};
module Alt: ALT with type t('a) = ImmutableArray.t('a) = {
include Functor;
let alt = (a, b) =>
ImmutableArray.(a |> to_ |> Js.Array.concat(to_(b)) |> from);
};
module Plus: PLUS with type t('a) = ImmutableArray.t('a) = {
include Alt;
let empty = ImmutableArray.from([||]);
};
open ImmutableArray;
let x = Plus.empty;
// Compiles
let x' = x |> push(1) |> push(2);
// Compiles, since the original array hasn't changed
let x'' = x |> push("foo");
// Doesn't compile, since x' has type ImmutableArray.t(int)
// let x''' = x' |> ImmutableArray.push("foo");
assert(x == from([||]));
assert(x' == from([|1, 2|]));
assert(x'' == from([|"foo"|]));
function push(x, xs) {
return xs.concat([x]);
}
var ImmutableArray = {
push: push
};
function map(f, xs) {
return xs.map(Curry.__1(f));
}
var Functor = {
map: map
};
function alt(a, b) {
return a.concat(b);
}
var Alt = {
map: map,
alt: alt
};
var empty = [];
var Plus = {
map: map,
alt: alt,
empty: empty
};
var xs = empty.concat([1]);
var x$prime = xs.concat([2]);
var x$prime$prime = empty.concat(["foo"]);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment