I'm struggling to find a generic type signature for a cons
cell, that allows for the selector function to be typed.
I.e. The code I want to be typed:
const cons = (head, tail) => selector => selector(head, tail);
I want to assign a generic type, where type T is the head and type V is the tail.
Some of my elaborate typing attempts have been:
const cons: <T,V>(head: T, rest: V) => (selector: (head: T, rest: V) => T | V) => T | V
= (head, rest) => selector => selector(head, rest);
The problem with the above code, is that I cannot find a type signature that works for the selector function head
, with the implementation:
const head = list => list((head, rest) => head)
I always get the error
"Expected 2 arguments but got 1." under list((head, rest) => head)
.
I just can't get the generic type to work! Any help would be greatly appreciated! Thank you!
const cons = (head, tail) => selector => selector(head, tail);
const head = list => list((head, tail) => head);
const rest = list => list((head, tail) => tail);
let someList = cons(1, cons(2, cons(3, null)));
head(someList);
// returns: 1
rest(someList);
// returns: cons(2, cons(3, null))
Your const
type is exactly the same as mine. I just split the many parts for clarity. The only new type I have added is the selectorFuncWrapper
, which I think is what you were looking for.
The original code is preserved. Check if it is good for you.
type selector<H, T> = (head: H, tail: T) => (H | T);
type selectorFunc<H, T> = (selector: selector<H, T>) => (H | T);
type consFunc<H, T> = (head: H, tail: T) => selectorFunc<H, T>;
type selectorFuncWrapper<H, T> = (list: selectorFunc<H, T>) => selectorFunc<H, T>;
const cons: consFunc<number, any> = (head, tail) => selector => selector(head, tail);
const head: selectorFuncWrapper<number, any> = list => list((head, tail) => head);
const rest: selectorFuncWrapper<number, any> = list => list((head, tail) => tail);
let someList = cons(1, cons(2, cons(3, null)));
head(someList);
// returns: 1
rest(someList);
// returns: cons(2, cons(3, null))