Skip to content

Instantly share code, notes, and snippets.

@cristianoc
Last active January 2, 2019 21:35
Show Gist options
  • Save cristianoc/0cb8afcfca272f17bb001ffa26983126 to your computer and use it in GitHub Desktop.
Save cristianoc/0cb8afcfca272f17bb001ffa26983126 to your computer and use it in GitHub Desktop.
module State: {
type t('a);
let createSlot: (t('a) => 'b) => 'b;
let useHook: ('a, t('a)) => ('a, 'a => unit);
} = {
type t('a) = ref(option('a));
let createSlot = cont => cont(ref(None));
let useHook = (initial: 'a, slot: t('a)) => {
let state =
switch (slot^) {
| None => initial
| Some(state) => state
};
let setState = value => {
Js.log2("setState", value);
slot := Some(value);
};
(state, setState);
};
};
module Effect: {
type t;
type callback = unit => unit;
let createSlot: unit => t;
let useHook: (callback, t) => unit;
} = {
type t = unit;
let createSlot = () => ();
type callback = unit => unit;
let useHook = (callback: callback, _slot: t) => callback();
};
module Run = {
let testState = testFunction =>
State.createSlot(slot => (slot, ()) |> testFunction);
let testEffect = testFunction => (Effect.createSlot(), ()) |> testFunction;
let testStateState = testFunction =>
State.createSlot(slot1 =>
State.createSlot(slot2 => (slot1, (slot2, ())) |> testFunction)
);
let testStateEffect = testFunction =>
State.createSlot(slot1 => {
let slot2 = Effect.createSlot();
(slot1, (slot2, ())) |> testFunction;
});
let testEffectState = testFunction =>
State.createSlot(slot2 => {
let slot1 = Effect.createSlot();
(slot1, (slot2, ())) |> testFunction;
});
let testStateStateState = testFunction =>
State.createSlot(slot1 =>
State.createSlot(slot2 =>
State.createSlot(slot3 =>
(slot1, (slot2, (slot3, ()))) |> testFunction
)
)
);
};
let useSlot = (useHook, slots, continuation) => {
let (slot, nextSlots) = slots;
continuation(nextSlots, useHook(slot));
};
let useState = (slots, initial) => useSlot(State.useHook(initial), slots);
let useEffect = (slots, callback) =>
useSlot(Effect.useHook(callback), slots);
let testIntState = slots =>
useState(
slots,
3,
(_nextSlots, (count, setCount)) => {
setCount(count + 1);
();
},
);
let runTestIntState = testIntState |> Run.testState;
let testStringState = slots =>
useState(
slots,
"",
(_nextSlots, (count, setCount)) => {
setCount(count ++ "x");
();
},
);
let runTestStringState = testStringState |> Run.testState;
let testStringIntState = slots =>
useState(
slots,
"",
(nextSlots, (count, setCount)) => {
setCount(count ++ "x");
nextSlots |> testIntState;
},
);
let runTestStringIntState = testStringIntState |> Run.testStateState;
/* let testConditionalWrong = (slots, cond) => {
cond ? slots |> testIntState : slots |> testStringState;
}; */
let testConditionalOK1 = (slots, cond) => {
cond ? slots |> testStringState : slots |> testStringIntState;
};
/* let testSequenceWrong = (slots) => {
slots |> testIntState;
slots |> testStringState;
}; */
let testSequenceOK = slots => {
slots |> testIntState;
slots |> testIntState;
};
let testEffectSequenceOK = slots =>
useEffect(
slots,
() => Js.log("hello"),
(nextSlots, ()) => nextSlots |> testSequenceOK,
);
let runTestEffectSequenceOK = testEffectSequenceOK |> Run.testEffectState;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment