There are two functions; funA and funB, respectively. a.i, a.o, ah, w, c are arrays in the function funA. The function funA shall be passed as a functional parameter to the function funB and the arrays should be able to be accessed by the function funB. Unfortunately, the syntax checker encountered an error "Error: Unbound record field a". Please comment, how to declare functional parameters in OCaml/ReasonML?
Full list
module Test = {
let vector = Array.init;
let matrix = (m, n, f) => vector(m, i => vector(n, f(i)));
let length = Array.length;
let rand = (x0, x1) => x0 +. Random.float(x1 -. x0);
let funA = (ni, nh, no) => {
let init = (fi, fo) => {
let i = matrix(ni + 1, nh, fi);
let o = matrix(nh, no, fo);
();
};
let a = {
let i = vector(ni + 1, _ => 1.0);
let o = vector(no, _ => 1.0);
();
};
let ah = vector(nh, _ => 1.0);
let w = init((_, _) => rand(-0.2, 0.4), (_, _) => rand(-2.0, 4.0));
let c = init((_, _) => 0.0, (_, _) => 0.0);
();
};
let funB = (net, inputs) => {
let (ni, nh, no) = (
length(net.a.i),
length(net.ah),
length(net.a.o),
);
();
};
};
To resolve the functional parameter funA which is inaccessible in the function funB, apply the following type at the beginning of the module.
module Test = {
type io('a) = {
i: 'a,
o: 'a,
};
type vec = array(float);
type mat = array(vec);
type funA = {
a: io(vec),
ah: vec,
w: io(mat),
c: io(mat),
};
.......
If I have a bunch of functions which strictly chain together, then it's easy enough to use compose to combine them:
f1 : A -> B
f2 : B -> C
f3 : C -> D
pipe(f1, f2, f3) : A -> D
Often I find that things aren't quite so perfect, and the information contained in A is needed again in a later stage:
f1 : A -> B
f2 : B -> C
f3 : (A, C) -> D
How do I elegantly compose these functions? I feel like I want some kind of "stash" to tuck the A into a Pair or something, map pipe(f1,f2) over the second element and then I have everything ready for f3. I can't come up with a very elegant way of doing this though, and it feels like a common enough situation that there must be an estalished pattern!
As an concrete example, say I have a string and I want to return it if it has an even length, otherwise I want to return none.
f1 = len
f2 = mod(2)
f3 = (s, m) => m == 0 ? Just(s) : None
How do I compose these together?
The type of function composition doesn't allow this. I think that a lambda along with currying is straightforward and more explicit than passing a tuple type through the composition:
const f1 = s => s.length;
const f2 = n => n % 2;
const f3 = s => m => m === 0 ? s : null;
const comp3 = f => g => h => x => f(g(h(x)));
const main = s => comp3(f3(s)) (f2) (f1) (s);
console.log(main("hallo"));
console.log(main("halloo"));
If you absolutely want it point free you can also utilize the fact that function composition may yield another function:
const f1 = s => s.length;
const f2 = n => n % 2;
const f3 = s => m => m === 0 ? s : null;
const comp3 = f => g => h => x => f(g(h(x)));
const join = f => x => f(x) (x); // monadic join
const flip = f => y => x => f(x) (y);
const main = join(comp3(flip(f3)) (f2) (f1));
console.log(main("hallo"));
console.log(main("halloo"));
Pretty hard to read though.
Just to elaborate a little on my comment on the original question - I have found a way of achieving what I want in quite a (IMO) nice style. It still feels like I'm reinventing the wheel though, so another way to rephrase the original question might be: do you recognise the function signatures below?
// stash :: A => [A,A]
const stash = x => [x, x];
// map :: (A => C) => [A,B] => [A,C]
const map = f => ([a, b]) => [a, f(b)];
// unstash :: ((A,B) => C) => [A,B] => C
const unstash = f => ([a, b]) => f(a, b);
const f1 = s => s.length;
const f2 = n => n % 2 === 0;
const f3 = (s, x) => x ? Option.some(s) : Option.none;
const getEvenName =
pipe(
stash,
map(f1),
map(f2),
unstash(f3)
);
getEvenName("Lucy") // Some("Lucy");
getEvenName("Tom") // None
const PAGESIZE = 1000;
const DEFAULTLINK = `${URL}/stuff?pageSize=${PAGESIZE}&apiKey=${APIKEY}`;
export const getAllStuff = (initialLink = DEFAULTLINK) => {
let allStuff = {};
return getSuffPage(initialLink)
.then(stuff => {
allStuff = stuff;
if (stuff.next) {
return getAllStuff(stuff.next)
.then(nextStuff => {
allStuff = Object.assign({}, stuff, nextStuff);
return allStuff;
});
} else {
return allStuff;
}
});
};
const getSuffPage = nextPageLink => {
fetch(nextPageLink).then(res => {
return res.json();
});
};
Calling getAllStuff throws:
Possible Unhandled Promise Rejection (id: 0):
TypeError: Cannot read property 'then' of undefined
TypeError: Cannot read property 'then' of undefined
at getAllStuff
I think it is usually because I do not return from a promise then or something but where don't I?
I've been working with anamorphisms or unfold in JavaScript lately and I thought I might share them with you using your program as a context to learn them in
const getAllStuff = async (initUrl = '/0') =>
asyncUnfold
( async (next, done, stuff) =>
stuff.next
? next (stuff, await get (stuff.next))
: done (stuff)
, await get (initUrl)
)
const get = async (url = '') =>
fetch (url) .then (res => res.json ())
To demonstrate that this works, we introduce a fake fetch and database DB with a fake delay of 250ms per request
const fetch = (url = '') =>
Promise.resolve ({ json: () => DB[url] }) .then (delay)
const delay = (x, ms = 250) =>
new Promise (r => setTimeout (r, ms, x))
const DB =
{ '/0': { a: 1, next: '/1' }
, '/1': { b: 2, next: '/2' }
, '/2': { c: 3, d: 4, next: '/3' }
, '/3': { e: 5 }
}
Now we just run our program like this
getAllStuff () .then (console.log, console.error)
// [ { a: 1, next: '/1' }
// , { b: 2, next: '/2' }
// , { c: 3, d: 4, next: '/3' }
// , { e: 5 }
// ]
And finally, here's asyncUnfold
const asyncUnfold = async (f, init) =>
f ( async (x, acc) => [ x, ...await asyncUnfold (f, acc) ]
, async (x) => [ x ]
, init
)
Program demonstration 1
const asyncUnfold = async (f, init) =>
f ( async (x, acc) => [ x, ...await asyncUnfold (f, acc) ]
, async (x) => [ x ]
, init
)
const getAllStuff = async (initUrl = '/0') =>
asyncUnfold
( async (next, done, stuff) =>
stuff.next
? next (stuff, await get (stuff.next))
: done (stuff)
, await get (initUrl)
)
const get = async (url = '') =>
fetch (url).then (res => res.json ())
const fetch = (url = '') =>
Promise.resolve ({ json: () => DB[url] }) .then (delay)
const delay = (x, ms = 250) =>
new Promise (r => setTimeout (r, ms, x))
const DB =
{ '/0': { a: 1, next: '/1' }
, '/1': { b: 2, next: '/2' }
, '/2': { c: 3, d: 4, next: '/3' }
, '/3': { e: 5 }
}
getAllStuff () .then (console.log, console.error)
// [ { a: 1, next: '/1' }
// , { b: 2, next: '/2' }
// , { c: 3, d: 4, next: '/3' }
// , { e: 5 }
// ]
Now say you wanted to collapse the result into a single object, we could do so with a reduce – this is closer to what your original program does. Note how the next property honors the last value when a key collision happens
getAllStuff ()
.then (res => res.reduce ((x, y) => Object.assign (x, y), {}))
.then (console.log, console.error)
// { a: 1, next: '/3', b: 2, c: 3, d: 4, e: 5 }
If you're sharp, you'll see that asyncUnfold could be changed to output our object directly. I chose to output an array because the sequence of the unfold result is generally important. If you're thinking about this from a type perspective, each foldable type's fold has an isomorphic unfold.
Below we rename asyncUnfold to asyncUnfoldArray and introduce asyncUnfoldObject. Now we see that the direct result is achievable without the intermediate reduce step
const asyncUnfold = async (f, init) =>
const asyncUnfoldArray = async (f, init) =>
f ( async (x, acc) => [ x, ...await asyncUnfoldArray (f, acc) ]
, async (x) => [ x ]
, init
)
const asyncUnfoldObject = async (f, init) =>
f ( async (x, acc) => ({ ...x, ...await asyncUnfoldObject (f, acc) })
, async (x) => x
, init
)
const getAllStuff = async (initUrl = '/0') =>
asyncUnfold
asyncUnfoldObject
( async (next, done, stuff) =>
, ...
)
getAllStuff ()
.then (res => res.reduce ((x, y) => Object.assign (x, y), {}))
.then (console.log, console.error)
// { a: 1, next: '/3', b: 2, c: 3, d: 4, e: 5 }
But having functions with names like asyncUnfoldArray and asyncUnfoldObject is completely unacceptable, you'll say - and I'll agree. The entire process can be made generic by supplying a type t as an argument
const asyncUnfold = async (t, f, init) =>
f ( async (x, acc) => t.concat (t.of (x), await asyncUnfold (t, f, acc))
, async (x) => t.of (x)
, init
)
const getAllStuff = async (initUrl = '/0') =>
asyncUnfoldObject
asyncUnfold
( Object
, ...
, ...
)
getAllStuff () .then (console.log, console.error)
// { a: 1, next: '/3', b: 2, c: 3, d: 4, e: 5 }
Now if we want to build an array instead, just pass Array instead of Object
const getAllStuff = async (initUrl = '/0') =>
asyncUnfold
( Array
, ...
, ...
)
getAllStuff () .then (console.log, console.error)
// [ { a: 1, next: '/1' }
// , { b: 2, next: '/2' }
// , { c: 3, d: 4, next: '/3' }
// , { e: 5 }
// ]
Of course we have to concede JavaScript's deficiency of a functional language at this point, as it does not provide consistent interfaces for even its own native types. That's OK, they're pretty easy to add!
Array.of = x =>
[ x ]
Array.concat = (x, y) =>
[ ...x, ...y ]
Object.of = x =>
Object (x)
Object.concat = (x, y) =>
({ ...x, ...y })
Program demonstration 2
Array.of = x =>
[ x ]
Array.concat = (x, y) =>
[ ...x, ...y ]
Object.of = x =>
Object (x)
Object.concat = (x, y) =>
({ ...x, ...y })
const asyncUnfold = async (t, f, init) =>
f ( async (x, acc) => t.concat (t.of (x), await asyncUnfold (t, f, acc))
, async (x) => t.of (x)
, init
)
const getAllStuff = async (initUrl = '/0') =>
asyncUnfold
( Object // <-- change this to Array for for array result
, async (next, done, stuff) =>
stuff.next
? next (stuff, await get (stuff.next))
: done (stuff)
, await get (initUrl)
)
const get = async (url = '') =>
fetch (url).then (res => res.json ())
const fetch = (url = '') =>
Promise.resolve ({ json: () => DB[url] }) .then (delay)
const delay = (x, ms = 250) =>
new Promise (r => setTimeout (r, ms, x))
const DB =
{ '/0': { a: 1, next: '/1' }
, '/1': { b: 2, next: '/2' }
, '/2': { c: 3, d: 4, next: '/3' }
, '/3': { e: 5 }
}
getAllStuff () .then (console.log, console.error)
// { a: 1, next: '/3', b: 2, c: 3, d: 4, e: 5 }
Finally, if you're fussing about touching properties on the native Array or Object, you can skip that and instead pass a generic descriptor in directly
const getAllStuff = async (initUrl = '/0') =>
asyncUnfold
( { of: x => [ x ], concat: (x, y) => [ ...x, ...y ] }
, ...
)
getAllStuff () .then (console.log, console.error)
// [ { a: 1, next: '/1' }
// , { b: 2, next: '/2' }
// , { c: 3, d: 4, next: '/3' }
// , { e: 5 }
// ]
I am new to selectors. I have created the following ones:
import { createSelector } from 'reselect';
const getValues = (state) => state.grid; // [3, 4, 7, 3, 2, 7, 3,...]
const getTiles = (state) => state.tiles; // [0, 1, 0, 1, 0, 0, 1,...]
// counts selected tiles (ie. adds up all the 1s)
export const getSelected = createSelector(
[getTiles],
tiles => tiles.reduce((acc, elem) => acc + elem, 0)
);
// displays only values of selected tiles, for the rest it shows 0
export const showSelected = createSelector(
[getTiles, getValues],
(tiles, grid) => tiles.map((idx, i) => (idx === 1 ? grid[i] : 0))
);
export const addSelected = createSelector(
[showSelected]
.....
);
/*
export const addSelected = createSelector(
[showSelected],
coun => coun.reduce((acc, elem) => acc + elem, 0)
);
*/
The third selector (addSelected - the last bottom, commented-out version) basically does the same thing as the first one (with different inputs). How can I make it more generic so I can reuse it instead of writing the whole 'reduce' line again?
You could just extract the reduce part into it's own function like this:
import { createSelector } from 'reselect'
...
// addElements adds all elements from given array
const addElements = elements =>
elements.reduce((acc, elem) => acc + elem, 0)
export const getSelected = createSelector([getTiles], addElements)
export const addSelected = createSelector([showSelected], addElements)
I hope this was helpful.
I'm relatively new to functional programming and libraries such as ramda.js but one thing I found very useful is the possibility of currying functions.
Using curried functions I write very often things as the following
const myFun = R.curry(
(arg1, arg2) => {
let calculated = anotherFun(arg1)
//do something with calculated and arg2
return calculated * 5 + arg2
}
)
const anotherFun = (arg) => {
console.log("calling anotherFun");
return arg + 1
}
var partial = myFun(1)
console.log(partial(2))
console.log(partial(3))
<script src="//cdn.jsdelivr.net/ramda/0.22.1/ramda.min.js"></script>
but clearly in this situation anotherFun is called every time I call partial even if in arg1 and as a consequence calculated are always the same.
Is there a way to optimize this behaviour and call anotherFun only when its args change?
The only way that crosses my mind is this
const myFun = R.curry(
(calculated, arg2) => {
return calculated * 5 + arg2
}
)
const anotherFun = (arg) => {
console.log("calling anotherFun");
return arg + 1
}
var calculated = anotherFun(1)
var partial = myFun(calculated)
console.log(partial(2))
console.log(partial(3))
<script src="//cdn.jsdelivr.net/ramda/0.22.1/ramda.min.js"></script>
but in this way I have to change the arguments passed to myFun and this complicates the external API
If you do the currying manually like this
const myFun = arg1 => arg2 => {
let calculated = anotherFun(arg1)
// do something with calculated and arg2
return calculated * 5 + arg2
};
you can also make this optimisation:
const myFun = arg1 => {
let calculated = anotherFun(arg1);
return arg2 => {
// do something with calculated and arg2
return calculated * 5 + arg2
};
};
I don't think Ramda will help you here with anything; and JavaScript compilers certainly are not doing this kind of optimisation.
#Bergi is right that Ramda will not offer you any help with this. If you want a Ramda-style result, where you can call with one parameter to get a function back or both to get the result you can do this:
const myFun = function(arg1, arg2) {
let calculated = anotherFun(arg1);
const newFunc = arg2 => {
return calculated * 5 + arg2
};
return (arguments.length < 2) ? newFunc : newFunc(arg2);
};
const with3 = myFun(3);
//: calling anotherFun
with3(1); //=> 21
with3(2); //=> 22
with3(4); //=> 23
myFun(2, 7);
//: calling anotherFun
//=> 22
myFun(2, 8);
//: calling anotherFun
//=> 23
This comes at the cost of not being able to use ES2015 arrow functions. But it might be worth it to you.
You can also rework this slightly to not build the internal function if both parameters are supplied, if that is important to you.
How about useWith and memoize from Ramda?
const myFun = R.useWith(
(a, b) => a * 5 + b,
[R.memoize(anotherFun), R.identity]
);