Skip to content

Instantly share code, notes, and snippets.

@gaku-sei
Created December 2, 2019 07:42
Show Gist options
  • Save gaku-sei/434d4de22dd66402728542cb9c3c7d35 to your computer and use it in GitHub Desktop.
Save gaku-sei/434d4de22dd66402728542cb9c3c7d35 to your computer and use it in GitHub Desktop.
Play with Indexed Monad in ReasonML (implements https://qiita.com/kimagure/items/a0ee7313e8c7690bf3f5)
open! IndexedBurger;
let burgerSpec: ixBurger(ready, topBunOn, burgerSpec) =
Infix.(
getEmptyPlate
>>=: placeEmptyBun
>>=: addKetchup
>>=: addPatty
>>=: addCheese
>>=: addTopBun
);
[@bs.deriving accessors]
type ixBurger('x, 'y, 'spec) =
| IxBurger('spec);
module IxFunctor:
Interfaces.IX_FUNCTOR with type t('x, 'y, 'a) = ixBurger('x, 'y, 'a) = {
type t('x, 'y, 'a) = ixBurger('x, 'y, 'a);
let imap = (f, IxBurger(spec)) => IxBurger(f(spec));
};
module IxApply:
Interfaces.IX_APPLY with type t('x, 'y, 'a) = ixBurger('x, 'y, 'a) = {
include IxFunctor;
let iapply = (IxBurger(f), IxBurger(spec)) => IxBurger(f(spec));
};
module IxApplicative:
Interfaces.IX_APPLICATIVE with type t('x, 'y, 'a) = ixBurger('x, 'y, 'a) = {
include IxApply;
let ipure = ixBurger;
};
module IxMonad:
Interfaces.IX_MONAD with type t('x, 'y, 'a) = ixBurger('x, 'y, 'a) = {
include IxApplicative;
let ibind = (IxBurger(spec), f) =>
f(spec) |> ((IxBurger(spec)) => spec) |> ixBurger;
};
module Infix = {
include Infix.IxFunctor(IxFunctor);
include Infix.IxApply(IxApply);
include Infix.IxApplicative(IxApplicative);
include Infix.IxMonad(IxMonad);
};
// Specific functions
let getEmptyPlate: ixBurger(ready, emptyPlate, burgerSpec) = IxBurger([]);
let addIngredient: (string, burgerSpec) => ixBurger('i, 'o, burgerSpec) =
(x, xs) => ixBurger([Ingredient(x), ...xs]);
let placeEmptyBun:
burgerSpec => ixBurger(emptyPlate, bottomBunOn, burgerSpec) =
addIngredient("Bottom bun");
let addKetchup: burgerSpec => ixBurger(bottomBunOn, bottomBunOn, burgerSpec) =
addIngredient("Ketchup");
let addPatty: burgerSpec => ixBurger(bottomBunOn, pattyOn, burgerSpec) =
addIngredient("Patty");
let addCheese: burgerSpec => ixBurger(pattyOn, cheeseOn, burgerSpec) =
addIngredient("Cheese");
let noCheese: burgerSpec => ixBurger(pattyOn, cheeseOn, burgerSpec) =
addIngredient("No cheese");
let addTopBun: burgerSpec => ixBurger(cheeseOn, topBunOn, burgerSpec) =
addIngredient("Top bun");
module IxFunctor = (IF: Interfaces.IX_FUNCTOR) => {};
module IxApply = (IA: Interfaces.IX_APPLY) => {
include IxFunctor(IA);
};
module IxApplicative = (IA: Interfaces.IX_APPLICATIVE) => {
include IxApply(IA);
};
module IxMonad = (IM: Interfaces.IX_MONAD) => {
include IxApply(IM);
let (>>=:) = IM.ibind;
};
module type IX_FUNCTOR = {
type t('x, 'y, 'a);
let imap: ('a => 'b, t('x, 'y, 'a)) => t('x, 'y, 'b);
};
module type IX_APPLY = {
include IX_FUNCTOR;
let iapply: (t('x, 'y, 'a => 'b), t('y, 'z, 'a)) => t('x, 'z, 'b);
};
module type IX_APPLICATIVE = {
include IX_APPLY;
let ipure: 'a => t('x, 'x, 'a);
};
module type IX_MONAD = {
include IX_APPLICATIVE;
let ibind: (t('x, 'y, 'a), 'a => t('y, 'z, 'b)) => t('x, 'z, 'b);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment