How to handle polymorphic type for both value and function? - flowtype

Consider the following type:
declare class Test<T> {
static of(value: T): Test<T>;
map<U>(fn: (value:T) => U): Test<U>;
}
Now for function ap, T is a function and it works like this:
Test.of(x => x * 2)
.ap(Test.of(5))
.map(console.log) // Output(number): 10
Test.of(x => `${x * 2}!`)
.ap(Test.of(5))
.map(console.log) // Output(string): 10!
So, to properly type check ap I need to do ap(Test<[get type of x]>): [type of output of T]
I tried Test<I, O>, where I is optional for values. But, it adds a lots of unnecessary thing to other functions. Is there any better way to solve this?
Note: I'm trying to write type definition for data.task

This is a tricky one! The ap() method can't be called on an instance of Test<T> for all T's, but only when T is a function that takes at most one argument.
So what you really need is something that is still TODO for Flow. It would look like this:
declare class Test<T> {
static of(value: T): Test<T>;
map<U>(fn: (value:T) => U): Test<U>;
ap<I,O>(this: Test<(in: I) => O>, test: Test<I>): Test<O>;
}
It declares that this must be a Test<T> where T is a function that takes I. Here's a GitHub issue about it.
In the meantime, you could do a first order approximation. It would look like this:
declare class Test<T> {
static of<I, O>(fn: (in: I) => O): FuncTest<I, O>;
static of(value: T): Test<T>;
map<U>(fn: (value:T) => U): Test<U>;
}
declare class FuncTest<I, O> extends Test<(in: I) => O> {
ap(x: Test<I>): Test<O>;
}
Test.of(x => x * 2)
.ap(Test.of(5))
.map(x => (x: number)) // no error
Test.of(x => `${x * 2}!`)
.ap(Test.of(5))
.map(x => (x: string)) // no error
Try this example on flowtype.org/try
The downside of this approach is that ap() returns Test<O>, even if O is a function. So you can't call ap() twice.
Test.of(x => Test.of(y => x * y))
.ap(Test.of(5))
.map(x => (x: Test<(y: number) => number>)); // This is fine
Test.of(x => Test.of(y => x * y))
.ap(Test.of(5))
.ap(Test.of(2)) // This is an error :(

Related

map function not accepting stream of 'Subjects'

I am missing something obvious, but I can't see it
export const subjectSelector: MemoizedSelector<
any,
Subject[]
> = new EntitySelectorsFactory().create<Subject>('subject').selectEntities;
this.store.pipe(
select(entitySelectors.subjectSelector),
map((s:Subject) => return {...s, z: {}}),
filter((subject:Subject) => subject.z.evidence && subject.z.evidence.length > 0)
);
select(entitySelectors.subjectSelector) is returning an array of Subject objects, but the compiler complains
Type 'Subject' is missing the following properties from type 'Subject[]': length, pop, push, concat, and 28 more.
map((s:Subject) => return {...s, z: {}}),
What am I missing?
Seems like you are confusing list and Observable map() function. This works for me assuming selectEntities returns the Ngrx Entity type Dictionary. The Parenthteses are hell though:
this.store.pipe(select(subjectSelector),
map((subjects: Dictionary<Subject>) => Object.values(subjects).map(s => ({...s, z: {}}))));
if 'subjects' is just a plain array, this will do:
this.store.pipe(select(subjectSelector),
map((subjects: Subject[]) => subjects.map(s => ({...s, z: {}}))));

Generate a predicate out of two predicates (job for monoid, fold?)

I have two predicates
interface Foo {}
interface Bar {}
declare const isFoo: (a:unknown):a is Foo
declare const isBar: (a:unknown):a is Bar
What is the functional way to combine two predicates to create a new predicate (for simplicity, let's assume it's a => isFoo(a) && isBar(a)?
With fp-ts, I initially thought I could fold(monoidAll)([isFoo, isBar]), but fold expects the array to be of booleans, not of functions that evaluate to boolean.
This works
import { monoid as M, function as F, apply as A, identity as I, reader as R } from 'fp-ts'
interface Foo{}
interface Bar{}
declare const isFoo:(a:unknown) => a is Foo
declare const isBar:(a:unknown) => a is Bar
const isFooAndBar = F.pipe(A.sequenceT(R.reader)(isFoo, isBar), R.map(M.fold(M.monoidAll)))
But boy howdy is that convoluted. I thought there could be another way. I ended up writing my own monoid that takes two predicates and combines them, calling it monoidPredicateAll:
const monoidPredicateAll:M.Monoid<Predicate<unknown>> = {
empty: ()=>true,
concat: (x,y) => _ => x(_) && y(_)
}
Is there a canonical FP way of combining two predicates? I know I could do something like
xs.filter(x => isFoo(x) && isBar(x))
But it can get complicated with more predicates, and re-using a monoid makes it less likely I'll do a typo like isFoo(x) || isBar(x) && isBaz(x) when I meant all && (and that's where a xs.filter(fold(monoidPredicateAll)(isFoo,isBar,isBaz)) would help out.
I found a discussion about this on SO, but it was about Java and a built-in Predicate type, so didn't directly address my question.
Yes, I'm overthinking this :)
I ended up doing this:
export const monoidPredicateAll:Monoid<Predicate<unknown>> = {
empty: ()=>true,
concat: (x,y) => _ => x(_) && y(_)
}
Then I could do
import {monoid as M} from 'fp-ts'
declare const isFoo: Predicate<number>
declare const isBar: Predicate<number>
const isFooAndBar = M.fold(monoidPredicateAll)([isFoo,isBar])
For others looking for a working solution, based on #user1713450's answer
import * as P from 'fp-ts/lib/Predicate';
import * as M from 'fp-ts/Monoid';
const createMonoidPredicateAll = <T>(): M.Monoid<P.Predicate<T>> => ({
empty: () => true,
concat: (x, y) => (_) => x(_) && y(_),
});
export const combine = <T>(predicates: P.Predicate<T>[]) =>
M.concatAll(createMonoidPredicateAll<T>())(predicates);

Make parameters available to all functions inside Ramda's pipe function

I'm using Ramda in node with express. I have a standard route:
app.get('/api/v1/tours', (req, res) => {
}
Where I'd like to compose functions using Ramda, but I write these functions outside the route (so they will be reusable in other routes).
For example:
function extractParams() {
return req.query.id;
}
function findXById(id) {
return xs.find(el => el.id == id);
}
function success(answer) {
return res.status(200).json(answer);
}
Now I want to compose those functions inside several routers. One of them will be:
app.get('/api/v1/tours', (req, res) => {
return R.pipe(extractParams, findXById, success)();
}
Is there any way I can prepare a generic wrapper that wraps the request and response objects on the routers to be available to these functions? I guess I'll
also have to change their signature.
I think what's really needed here is a version of pipe that accepts some initial arguments and returns a new function that will accept the remaining ones, with all the functions having such a dual-application signature. I came up with the following doublePipe implementation that does this:
const doublePipe = (...fns) => (...initialArgs) =>
pipe (...(map (pipe (apply, applyTo (initialArgs)), fns) ))
const foo = (x, y) => (z) => (x + y) * z
const bar = (x, y) => (z) => (x + y) * (z + 1)
const baz = doublePipe (foo, bar)
console .log (
baz (2, 4) (1) //=> (2 + 4) * (((2 + 4) * 1) + 1) => 42
// / \ '------+----'
// bar ( x --/ , `-- y , `-- z, which is foo (2, 4) (1) )
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script>const {pipe, map, apply, applyTo} = R </script>
Note that the functions foo and bar will both receive the same x and y arguments, and that foo (x, y) will receive the z argument supplied from the outside, with its result passed as z to bar (x, y).
This is an interesting function, and it's a fairly useful generic solution to this sort of problem. But it won't work in your Express environment, because the handlers need to have the signature (req, res) => ... and not (req, res) => (...args) => ....
So below is an alternative, which mimics a trivial Express-like environment and uses a slightly different doublePipe version, which does not take an additional invocation, simply calling the first function with no parameters, and then sequentially passing the results through to the others as expected. This means the first function to doublePipe must have the signature (req, res) => () => ..., while the others have (req, res) => (val) => .... While we could fix it so that that the first one was just (req, res) => ..., it seems to me that this inconsistency would not be helpful.
const doublePipe = (...fns) => (...initialArgs) =>
reduce (applyTo, void 0, map (apply (__, initialArgs), fns))
const xs = [{id: 1, val: 'abc'}, {id: 2, val: 'def'},{id: 3, val: 'ghi'}, {id: 4, val: 'jkl'}]
const extractParams = (req, res) => () => req .query .id
const findXById = (xs) => (req, res) => (id) => xs .find (el => el .id == id)
const success = (req, res) => (answer) => res .status (200) .json (answer)
app .get ('/api/v1/tours', doublePipe (extractParams, findXById (xs), success))
console .log (
app .invoke ('get', '/api/v1/tours?foo=bar&id=3')
)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script>
const {__, map, reduce, applyTo, apply, head, compose, split, objOf, fromPairs, last} = R
// Minimal version of Express, only enough for this demo
const base = compose (head, split ('?'))
const makeRequest = compose (objOf ('query'), fromPairs, map (split ('=')), split ('&'), last, split ('?'))
const makeResponse = () => {
const response = {
status: (val) => {response .status = val; return response},
json: (val) => {response.body = JSON .stringify (val); delete response.json; return response}
}
return response
}
const app = {
handlers: {get: {}, post: {}},
get: (route, handler) => app .handlers .get [route] = handler,
invoke: (method, route) =>
app .handlers [method] [base (route)] (makeRequest (route), makeResponse ())
}
</script>
findById does not have the required signature, but findById(xs) does, so that's what we pass into pipe.
Finally, note that Ramda and Express may never play particularly well together, as the handlers sent to Express are meant to modify their parameters, and Ramda is designed to never mutate input data. That said, this seems to work reasonably well for these requirements.
Update: explanation of doublePipe
A comment seemed to indicate that a more complete description of doublePipe was in order. I will only discuss the second version,
const doublePipe = (...fns) => (...initialArgs) =>
reduce (applyTo, void 0, map (apply (__, initialArgs), fns))
Here are two possible calls:
// foo :: (a, b) -> f
const foo = doublePipe (
f1, // :: (a, b) -> Void -> (c)
f2, // :: (a, b) -> c -> d
f3, // :: (a, b) -> d -> e
f4, // :: (a, b) -> e -> f
)
// bar :: (a, b, c) -> f
const bar = doublePipe (
g1, // :: (a, b, c) -> Void -> d
g2, // :: (a, b, c) -> d -> e
g3, // :: (a, b, c) -> e -> f
)
If you're not familiar with the Hindley-Milner signatures (such as (a, b) -> c -> d above), I wrote a long article on the Ramda wiki about their uses in Ramda. The foo function is built by passing f1 - f4 to doublePipe. The resulting function takes parameters of types a and b (req and res in your example) and returns a value of type f. Similarly bar is created by supplying g1 - g3 to doublePipe, returning a function that accepts parameters of types a, b, and c and returning a value of type f.
We can rewrite doublePipe a bit more imperatively to show the steps taken:
const doublePipe = (...fns) => (...initialArgs) => {
const resultFns = map (apply (__, initialArgs), fns)
return reduce (applyTo, void 0, resultFns)
}
and expanding that a bit, this might also look like
const doublePipe = (...fns) => (...initialArgs) => {
const resultFns = map (fn => fn(...initialArgs), fns)
return reduce ((value, fn) => fn (value), undefined, resultFns)
}
In the first line, we partially apply the initial arguments to each of the supplied functions, giving us a list of simpler functions. For foo resultFns would look like [f1(req, res), f2(req, res), f3(req, res), f4(req, res)], which would have signatures [Void -> c, c -> d, d -> e, e -> f]. We could now choose to pipe those functions and call the resulting function (return pipe(...resultFns)()), but I didn't see a good reason to create the piped function only to call it a single time and throw it away, so I reduce over that list, starting with undefined and passing the result of each one to the next.
I tend to think in terms of Ramda functions, but you could write this easily enough without them:
const doublePipe = (...fns) => (...initialArgs) =>
fns
.map (fn => fn (...initialArgs))
.reduce ((value, fn) => fn (value), void 0)
I hope this made that clearer!
Your three functions do not have the things they need in their declared scope. You need to modify their signature first:
function extractParams(req) { //<-- added `req`
return req.query.id;
}
function findXById(id, xs) { //<-- added `xs`
return xs.find(el => el.id == id);
}
function success(res, answer) { //<-- added `res`
return res.status(200).json(answer);
}
Note that the order of the parameters isn't "random". The data you need to operate on should be the last as it allows for a nicer function composition experience. It's one of the tenet of Ramda:
The parameters to Ramda functions are arranged to make it convenient for currying. The data to be operated on is generally supplied last.
Source: https://ramdajs.com/
This is not enough though. You need to curry some of them. Why? While the "recipe" of your function composition looks the same, each individual function operate on a specific data. This will make sense later, let's curry first:
const extractParams = (req) => req.query.id;
const findXById = R.curry((id, xs) => xs.find(el => el.id == id));
const success = R.curry((res, answer) => res.status(200).json(answer));
Now you can build a function composition whilst supplying some specific parameter to your functions in the composition:
app.get('/api/v1/tours', (req, res) =>
R.pipe(
extractParams,
findXById(42),
success(res))
(req));
It's important to note that while there is nothing "wrong" with this, it's also missing the point:
R.pipe(extractParams, findXById, success)()
Why? R.pipe or R.compose (or R.o) returns a function composition which is itself a function that you call with parameters (just one with R.o but let's ignore that for now). So you need to think about the data that goes through your function composition. In your case it's probably req:
R.pipe(extractParams, findXById, success)(req)
Each function in your function composition receives as its parameter, the result of the previous function. If something in between doesn't depend on that, then perhaps that function shouldn't be part of the composition. (Take that advice with a pinch of salt; special conditions may apply; just think about it ;)

How to specify a list of generics of unknown/arbitrary size

Note: I started a discussion on Github about this subject.
I have a zip function, for now it is typed for iterables of the same type T. I would like to have this typed for arbitrary mixed input type but still conserving the matching output type, for example, if the input type [Iterable<T>, Iterable<U>] I want the output type to be Iterable<[T, U]>. Is it possible to have this for arbitrary input size? I basically want to say, if you have this list of type as input you'll have them as output.
Here is the current version of my zip:
export function *zip<T>(...iterables:Array<Iterable<T>>): Iterable<Array<T>> {
const iterators = iterables.map(iterable => iter(iterable));
while(true){
const items = iterators.map(iterator => iterator.next());
if (items.some(item => item.done)){
return;
}
yield ((items.map(item => { return item.value }): Array<any>): Array<T>);
}
}
export function *iter<T>(iterable:Iterable<T>): Iterator<T> {
yield* iterable;
}
Current best solution by AndrewSouthpaw:
declare function zip<A, B>(Iterable<A>, Iterable<B>): Iterable<[A, B]>;
declare function zip<A, B, C>(Iterable<A>, Iterable<B>, Iterable<C>): Iterable<[A, B, C]>;
declare function zip<A, B, C, D>(Iterable<A>, Iterable<B>, Iterable<C>, Iterable<D>): Iterable<[A, B, C, D]>;
export function *zip<T>(...iterables:Array<Iterable<T>>): Iterable<Array<T>> {
const iterators = iterables.map(iterable => iter(iterable));
while(true){
const items = iterators.map(iterator => iterator.next());
if (items.some(item => item.done)){
return;
}
yield ((items.map(item => { return item.value }): Array<any>): Array<T>);
}
}
It works as expected when called with 4, 3 or 2 iterables, when called with 5 or more arguments flow will simply say that zip can only be called with 4 or less arguments. Of course we could add as many function signature as we like to get it to work for 5, 6 or any number N of arguments, but that would require to declare N distinct signatures (which is a bit ugly). On the other hand this strategy does not allow to have an unbounded number of arguments (like the spread operator does). I'm still looking for that.
This raised a more general question, is there any language in which this exists?
I really have the feeling that this can be done in theory (not necessarily in flow), on the other hand I can't recall of a statically typed language in which I've done/seen that (I would also be interested in seeing this kind of type checking in any language).
To be a bit more specific, my feeling is that if you have a type checking system in which (by definition) all types are statically known (any variable has a known type x) then function f: Array<Iterable<x>> -> Iterable<Array<x>> is always called on a known type x. Therefore we should be able to statically decide what type f will return given x (whether x is a single generic type or a list of generic types).
The same goes for the function itself, if you have a type x as input, then you only need to check that your function preserve type x.
Maybe this needs to be defined recursively in some languages, that would also be interesting to see.
We've only been able to accomplish this through overriding the function signature declaration. This might help:
declare function zip<A, B>(Iterable<A>, Iterable<B>): Iterable<[A, B]>
declare function zip<A, B, C>(Iterable<A>, Iterable<B>, Iterable<C>): Iterable<[A, B, C]>
declare function zip<A, B, C, D>(Iterable<A>, Iterable<B>, Iterable<C>, Iterable<D>): Iterable<[A, B, C, D]>
export function zip(a, b, c, d) {
/* ... */
}
Here is the working solution. All credit goes to jbrown215 from Flow team, he found the idea of using $ReadOnlyArray<mixed> here:
export function *zip<T: $ReadOnlyArray<mixed>>(...iterables:Array<Iterable<T>>): Iterable<Array<T>> {
const iterators = iterables.map(iterable => iter(iterable));
while(true){
const items = iterators.map(iterator => iterator.next());
if (items.some(item => item.done)){
return;
}
yield ((items.map(item => { return item.value }): Array<any>): Array<T>);
}
}
export function *iter<T>(iterable:Iterable<T>): Iterator<T> {
yield* iterable;
}

Using promises with setTimeout

I am new to Reason, currently trying to convert a personal project from js to reason. Mostly it has been easy so far apart from async stuff.
I am not able to call my function recursively with delay.
I have a function getPrice which returns a promise of int
type getPrice = unit => Js.Promise.t(int)
I want to make another function checkPrice, which checks the current price by given user price endlessly unless condition is met.
let rec checkPrice = (userPrice) =>
Js.Promise.(
getPrice()
|> then_(
(currentPrice) =>
if (currentPrice >= userPrice) {
resolve(currentPrice)
} else {
/* call this function with setTimeout */
checkPrice(userPrice)
}
)
);
But I am getting type mismatch saying setTimeout should be of type unit
The Js.Promise API is unfortunately absolutely terrible, mostly because the JS API is just plain unsound, but it's not very well thought out on the Reason side either. There might be some convenience fixes coming to Js.Promise, but hopefully the entire thing is replaced with a proper solution in the not too distant future.
In the here and now, however, you'll have to do something like this:
external toExn : Js.Promise.error => exn = "%identity";
let rec checkPrice = (userPrice) =>
Js.Promise.(
getPrice()
|> then_(
(currentPrice) =>
if (currentPrice >= userPrice) {
resolve(currentPrice)
} else {
Js.Promise.make((~resolve, ~reject) =>
Js.Global.setTimeout(
fun () =>
checkPrice(userPrice)
|> then_((v) => [#bs] resolve(v) |> Js.Promise.resolve)
|> catch((e) => [#bs] reject(toExn(e)) |> Js.Promise.resolve)
|> ignore,
0
) |> ignore
)
}
)
);

Resources