Skip to content

Instantly share code, notes, and snippets.

@gaku-sei
Created December 2, 2019 06:00
Show Gist options
  • Save gaku-sei/a0acd1f90876d80856194adb76e8e60a to your computer and use it in GitHub Desktop.
Save gaku-sei/a0acd1f90876d80856194adb76e8e60a to your computer and use it in GitHub Desktop.
Play with "void-like" types to re-produce Elm's Task
// Rough implementation of https://package.elm-lang.org/packages/elm/core/latest/Platform-Cmd#Cmd
module Cmd = {
[@bs.deriving accessors]
type t('msg) =
| Cmd('msg);
let make: 'msg => t('msg) = cmd;
};
// Simple https://package.elm-lang.org/packages/elm/core/latest/Task
module Task = {
type t('error, 'ok) =
| Simple('ok): t([> | `void], 'ok) // Here's the void-like trick using GADT
| Failable(result('ok, 'error)): t([> | `error('error)], 'ok);
let perform: ('a => 'msg, t([ | `void], 'a)) => Cmd.t('msg) =
(f, Simple(a)) => Cmd.make(f(a));
let attempt:
(result('a, 'error) => 'msg, t([ | `error('error)], 'a)) => Cmd.t('msg) =
(f, Failable(result)) => Cmd.make(f(result));
let simple: (unit => 'a) => t([ | `void], 'a) = f => Simple(f());
let failable: (unit => result('a, 'error)) => t([ | `error('error)], 'a) =
f => Failable(f());
};
// Some dumb common tasks
module CommonTasks = {
let now = Task.simple(const(42));
let fetch = Task.failable(() => (Ok("foo"): result(string, exn)));
};
// And how to use the tasks
module UseTask = {
[@bs.deriving accessors]
type msg =
| GotTime(int)
| FetchDone(result(string, exn));
let cmd1 = Task.perform(gotTime, CommonTasks.now);
let cmd2 = Task.attempt(fetchDone, CommonTasks.fetch);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment