How to declare functional parameters in OCaml/ReasonML? - functional-programming

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),
};
.......

Related

Rust collect() chunks of a vector into Vec<Vec<bool>>

I have a vector outputs of u64 which basically only has 0s and 1s. And I want to split the vector into equal parts to get a Vec<Vec<bool>> or Vec<&[bool]].
However, somehow I can't do it it tells me
256 | .collect();
| ^^^^^^^ value of type `std::vec::Vec<std::vec::Vec<bool>>` cannot be built from `std::iter::Iterator<Item=bool>`
using
let sqrt_output = (outputs.len() as f64).sqrt() as usize;
let output_grid: Vec<&[bool]> = outputs
.chunks(sqrt_output)
.map(|s| {
match s {
[1_u64] => true,
[0_u64] => false,
// this is a hack but I don't know how to return an error ...
_ => true,
}
})
.collect();
To get back a Vec<Vec<bool>> your map closure would need to return a Vec<bool>
Here's an example:
fn main() {
let outputs: Vec<u64> = vec![0, 1, 1, 0];
let output_grid: Vec<Vec<bool>> = outputs
.chunks(2)
.map(|s| { // this is an &[u64]
let mut inner_vec = Vec::new();
for val in s {
inner_vec.push(match val {
1 => true,
0 => false,
_ => panic!("illegal number") // can just avoid push-ing if you want to ignore other numbers
})
}
inner_vec
})
.collect();
// this prints "[[false, true], [true, false]]"
println!("{:?}", output_grid)
}

How to pass data to a later stage of a compose pipeline

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

Reverse arguments order in curried function (ramda js)

I have a higher order function: let's say for simplicity
const divideLeftToRight = x => y => x/y;
I would like to have a function that performs the division but from 'right to left'. In other words, I need to have:
const divideRightToLeft = x => y => y/x;
I thought about doing:
const divideRightToLeft = R.curry((x,y) => divideLeftToRight(y)(x));
I am wondering if there is a more elegant way to do it
You are looking for the flip function:
const divideRightToLeft = R.flip(divideLeftToRight)
You could uncurry the function before flipping. (flip returns a curried function.)
E.g.
const divideRightToLeft = R.flip(R.uncurryN(2, divideLeftToRight))
Alternatively, you can define a custom flipCurried function:
// https://github.com/gcanti/fp-ts/blob/15f4f701ed2ba6b0d306ba7b8ca9bede223b8155/src/function.ts#L127
const flipCurried = <A, B, C>(fn: (a: A) => (b: B) => C) => (b: B) => (a: A) => fn(a)(b);
const divideRightToLeft = flipCurried(divideLeftToRight)

How can I convert this large factorial function to a higher-order function?

The following code uses a cache object outside of the factorial function. The factorial function itself is large which has too many concerns of finding factorial and caching.
How can I convert this code to a higher-order function and generate the same result when I call
console.log(factorial(5));
console.log(factorial(7));
cache = { }
function factorial(n) {
if (n === 0) {
return 1;
}
if (cache[n])
{
return cache[n];
}
console.log("Stack Up: " + n);
var value = n * factorial(n - 1);
console.log("Stack Down: " + value);
cache[n] = value;
return value;
}
console.log(factorial(5));
console.log(factorial(7));
There's already other answers out there for memoising recursive functions, but I'll adapt that answer to factorial in javascript so you can see how it works more easily
The secret to writing memoised recursive functions is continuation passing style. A similar technique works when you want to make a non-tail recursive function stack-safe.
I'll leave some console.log statements in this first example so you can see when it's actually computing and when it's just doing a memo lookup.
const memoise = f => {
const memo = new Map()
const compute = (x, k) =>
(console.log('compute', x),
memo.get(x, memo.set(x, f(x,k))))
const lookup = x =>
(console.log('lookup', x),
memo.has(x) ? memo.get(x) : compute(x, lookup))
return lookup
}
const factk = (x, k) => {
if (x === 0)
return 1
else
return x * k(x - 1)
}
const memfact = memoise(factk)
console.log(memfact(5)) // 120
console.log(memfact(7)) // 5040
Here I've removed the console.log calls inside of memoise and instead demonstrate a memoised fibonacci function vs an unmemoised one. Compare the dramatic time difference between memoise(fibk) and badfib
const memoise = f => {
const memo = new Map()
const compute = (x, k) =>
memo.get(x, memo.set(x, f(x,k)))
const lookup = x =>
memo.has(x) ? memo.get(x) : compute(x, lookup)
return lookup
}
const fibk = (x, k) => {
if (x < 2)
return x
else
return k(x - 1) + k(x - 2)
}
const badfib = x => {
if (x < 2)
return x
else
return badfib(x - 1) + badfib(x - 2)
}
console.time('memoised')
console.log(memoise (fibk) (35)) // 9227465 1.46ms
console.timeEnd('memoised')
console.time('unmemoised')
console.log(badfib(35)) // 9227465 135.85ms
console.timeEnd('unmemoised')

Most efficient way to fill a vector from back to front

I am trying to populate a vector with a sequence of values. In order to calculate the first value I need to calculate the second value, which depends on the third value etc etc.
let mut bxs = Vec::with_capacity(n);
for x in info {
let b = match bxs.last() {
Some(bx) => union(&bx, &x.bbox),
None => x.bbox.clone(),
};
bxs.push(b);
}
bxs.reverse();
Currently I just fill the vector front to back using v.push(x) and then reverse the vector using v.reverse(). Is there a way to do this in a single pass?
Is there a way to do this in a single pass?
If you don't mind adapting the vector, it's relatively easy.
struct RevVec<T> {
data: Vec<T>,
}
impl<T> RevVec<T> {
fn push_front(&mut self, t: T) { self.data.push(t); }
}
impl<T> Index<usize> for RevVec<T> {
type Output = T;
fn index(&self, index: usize) -> &T {
&self.data[self.len() - index - 1]
}
}
impl<T> IndexMut<usize> for RevVec<T> {
fn index_mut(&mut self, index: usize) -> &mut T {
let len = self.len();
&mut self.data[len - index - 1]
}
}
The solution using unsafe is below. The unsafe version is slightly more than 2x as fast as the safe version using reverse(). The idea is to use Vec::with_capacity(usize) to allocate the vector, then use ptr::write(dst: *mut T, src: T) to write the elements into the vector back to front. offset(self, count: isize) -> *const T is used to calculate the offset into the vector.
extern crate time;
use std::fmt::Debug;
use std::ptr;
use time::PreciseTime;
fn scanl<T, F>(u : &Vec<T>, f : F) -> Vec<T>
where T : Clone,
F : Fn(&T, &T) -> T {
let mut v = Vec::with_capacity(u.len());
for x in u.iter().rev() {
let b = match v.last() {
None => (*x).clone(),
Some(y) => f(x, &y),
};
v.push(b);
}
v.reverse();
return v;
}
fn unsafe_scanl<T, F>(u : &Vec<T> , f : F) -> Vec<T>
where T : Clone + Debug,
F : Fn(&T, &T) -> T {
unsafe {
let mut v : Vec<T> = Vec::with_capacity(u.len());
let cap = v.capacity();
let p = v.as_mut_ptr();
match u.last() {
None => return v,
Some(x) => ptr::write(p.offset((u.len()-1) as isize), x.clone()),
};
for i in (0..u.len()-1).rev() {
ptr::write(p.offset(i as isize), f(v.get_unchecked(i+1), u.get_unchecked(i)));
}
Vec::set_len(&mut v, cap);
return v;
}
}
pub fn bench_scanl() {
let lo : u64 = 0;
let hi : u64 = 1000000;
let v : Vec<u64> = (lo..hi).collect();
let start = PreciseTime::now();
let u = scanl(&v, |x, y| x + y);
let end= PreciseTime::now();
println!("{:?}\n in {}", u.len(), start.to(end));
let start2 = PreciseTime::now();
let u = unsafe_scanl(&v, |x, y| x + y);
let end2 = PreciseTime::now();
println!("2){:?}\n in {}", u.len(), start2.to(end2));
}

Resources