Skip to content

Instantly share code, notes, and snippets.

@jchavarri
Created January 6, 2019 16:01
Show Gist options
  • Select an option

  • Save jchavarri/e90f1f49df51922989b200f81d925202 to your computer and use it in GitHub Desktop.

Select an option

Save jchavarri/e90f1f49df51922989b200f81d925202 to your computer and use it in GitHub Desktop.

Revisions

  1. jchavarri created this gist Jan 6, 2019.
    88 changes: 88 additions & 0 deletions PureSlots.re
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,88 @@
    module type SlotsType = {
    type t('slot, 'nextSlots);
    let create: unit => t('slot, 'nextSlots);
    let use:
    (
    ~default: 'slot,
    (('slot, t('slot2, 'nextSlots))) => 'c,
    t('slot, t('slot2, 'nextSlots))
    ) =>
    ('c, 'slot);
    };

    module Slots: SlotsType = {
    type t('slot, 'nextSlots) = option(('slot, 'nextSlots));
    let create = () => None;
    let use = (~default, continuation, slots: t(_)) =>
    switch (slots) {
    | None =>
    let slot = default;
    let nextSlots = create();
    let next = (slot, nextSlots);
    (continuation(next), slot);
    | Some((slot, nextSlots)) =>
    let next = (slot, nextSlots);
    (continuation(next), slot);
    };
    };

    type element = int;
    type hook('slot, 'nextSlots) = (element, Slots.t('slot, 'nextSlots));

    let useState = (initial, slots) => slots |> Slots.use(~default=initial);

    let primitive: 'a => 'a = x => x;

    module type Component = {
    type element;
    type slots;
    type createElement;
    let createElement: createElement;
    let createSlots: unit => Slots.t(slots, _);
    };

    let createComponent =
    (type c, type e, type s, create: ((e, s) => (e, s), Slots.t(s, _)) => c)
    : (module Component with
    type createElement = c and type element = e and type slots = s) =>
    (module
    {
    type element = e;
    type slots = s;
    type createElement = c;
    let createSlots = () => Slots.create();
    let createElement =
    create((element, slot) => (element, slot), createSlots());
    });

    module MyComponent = (
    val createComponent((render, slots, ~one, ~two) =>
    render(
    useState(
    3,
    ((state, slots)) =>
    useState(
    "3",
    ((stateStr, _slots)) =>
    primitive(one + two + state + int_of_string(stateStr)),
    slots,
    ),
    slots,
    ),
    )
    )
    );

    let test = (slots) =>
    useState(
    3,
    ((state, slots)) =>
    useState(
    "3",
    ((stateStr, _slots)) => state + int_of_string(stateStr),
    slots,
    ),
    slots,
    );

    let (slot, element) = test(Slots.create());