Skip to content

Instantly share code, notes, and snippets.

@jchavarri
Created January 7, 2019 13:39
Show Gist options
  • Select an option

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

Select an option

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

Revisions

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

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

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

    let primitive: 'a => 'a = x => x;
    type element = int;
    type opaqueSlots =
    | OpaqueSlots(Slots.t('slot, 'nextSlots)): opaqueSlots;

    module type Component = {
    type slots;
    type createElement;
    let createElement: createElement;
    };

    let createComponent =
    (
    type c,
    type s,
    create:
    (
    (Slots.t(s, _) => element, ~children: list(element), opaqueSlots) =>
    element
    ) =>
    c,
    )
    : (module Component with type createElement = c and type slots = s) =>
    (module
    {
    type slots = s;
    type createElement = c;
    let createElement =
    create((userRender, ~children) => {
    ignore(children);
    (OpaqueSlots(slots)) => {
    /* Error: This expression has type
    ($OpaqueSlots_'slot, $OpaqueSlots_'nextSlots) Slots.t
    but an expression was expected of type (slots, 'a) Slots.t
    Type $OpaqueSlots_'slot is not compatible with type slots */
    let childElement = userRender(slots);
    childElement;
    };
    });
    });

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

    let comp = <MyComponent one=1 two=2 />;