Last active
February 10, 2020 13:06
-
-
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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"|])); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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