Skip to content

Instantly share code, notes, and snippets.

@jchavarri
Created January 6, 2019 11:29
Show Gist options
  • Save jchavarri/898232f3568f86b0a593269efb8461a0 to your computer and use it in GitHub Desktop.
Save jchavarri/898232f3568f86b0a593269efb8461a0 to your computer and use it in GitHub Desktop.
SlotsCreateComponent.re
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;
module type Component = {
type element;
type slots;
type nextSlots;
type createElement;
let createElement: createElement;
let createSlots: unit => Slots.t(slots, nextSlots);
};
let createComponent =
(type c, type e, type s, type n, create: (e => e, Slots.t(s, n)) => c)
: (module Component with
type createElement = c and
type element = e and
type slots = s and
type nextSlots = n) =>
(module
{
type element = e;
type slots = s;
type nextSlots = n;
type createElement = c;
let createSlots = () => Slots.create();
let createElement = create(x => x, createSlots());
});
/* This fails with:
Error: The type of this packed module contains variables:
(module Component with type createElement = one:int -> two:int -> int and type element =
int and type nextSlots = ('a, 'b) Slots.t and type slots = int)
*/
module IntComponent = (
val createComponent((render, slots, ~one, ~two) =>
render(
{
let (state, _nextSlots) = useState(3, slots);
primitive(one + two + state);
},
)
)
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment