How to compose functions in Rust? - functional-programming

I'm trying to write a function that composes two functions. The initial design is pretty simple: a function that takes two functions and returns a composed function which I can then compose with other functions, since Rust doesn't have rest parameters. I've run into a wall built with frustrating non-helpful compiler errors.
My compose function:
fn compose<'a, A, B, C, G, F>(f: F, g: G) -> Box<Fn(A) -> C + 'a>
where
F: 'a + Fn(A) -> B + Sized,
G: 'a + Fn(B) -> C + Sized,
{
Box::new(move |x| g(f(x)))
}
How I would like to use it:
fn main() {
let addAndMultiply = compose(|x| x * 2, |x| x + 2);
let divideAndSubtract = compose(|x| x / 2, |x| x - 2);
let finally = compose(*addAndMultiply, *divideAndSubtract);
println!("Result is {}", finally(10));
}
The compiler doesn't like that, no matter what I try, the trait bounds are never satisfied. The error is:
error[E0277]: the size for values of type `dyn std::ops::Fn(_) -> _` cannot be known at compilation time
--> src/main.rs:13:19
|
13 | let finally = compose(*addAndMultiply, *divideAndSubtract);
| ^^^^^^^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `dyn std::ops::Fn(_) -> _`
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
note: required by `compose`
--> src/main.rs:1:1
|
1 | / fn compose<'a, A, B, C, G, F>(f: F, g: G) -> Box<Fn(A) -> C + 'a>
2 | | where
3 | | F: 'a + Fn(A) -> B + Sized,
4 | | G: 'a + Fn(B) -> C + Sized,
5 | | {
6 | | Box::new(move |x| g(f(x)))
7 | | }
| |_^

As #ljedrz points out, to make it work you only need to reference the composed functions again:
let finally = compose(&*multiply_and_add, &*divide_and_subtract);
(Note that in Rust, convention dictates that variable names should be in snake_case)
However, we can make this better!
Since Rust 1.26, we can use abstract return types (previously featured gated as #![feature(conservative_impl_trait)]). This can help you simplify your example greatly, as it allows you to skip the lifetimes, references, Sized constraints and Boxes:
fn compose<A, B, C, G, F>(f: F, g: G) -> impl Fn(A) -> C
where
F: Fn(A) -> B,
G: Fn(B) -> C,
{
move |x| g(f(x))
}
fn main() {
let multiply_and_add = compose(|x| x * 2, |x| x + 2);
let divide_and_subtract = compose(|x| x / 2, |x| x - 2);
let finally = compose(multiply_and_add, divide_and_subtract);
println!("Result is {}", finally(10));
}
Finally, since you mention rest parameters, I suspect that what you actually want is to have a way to chain-compose as many functions as you want in a flexible manner. I wrote this macro for this purpose:
macro_rules! compose {
( $last:expr ) => { $last };
( $head:expr, $($tail:expr), +) => {
compose_two($head, compose!($($tail),+))
};
}
fn compose_two<A, B, C, G, F>(f: F, g: G) -> impl Fn(A) -> C
where
F: Fn(A) -> B,
G: Fn(B) -> C,
{
move |x| g(f(x))
}
fn main() {
let add = |x| x + 2;
let multiply = |x| x * 2;
let divide = |x| x / 2;
let intermediate = compose!(add, multiply, divide);
let subtract = |x| x - 2;
let finally = compose!(intermediate, subtract);
println!("Result is {}", finally(10));
}

Just add references in finally and it will work:
fn main() {
let addAndMultiply = compose(|x| x * 2, |x| x + 2);
let divideAndSubtract = compose(|x| x / 2, |x| x - 2);
let finally = compose(&*addAndMultiply, &*divideAndSubtract);
println!("Result is {}", finally(10));
}
Dereferencing addAndMultiply or divideAndSubtract uncovers a trait object which is not Sized; it needs to either be wrapped in a Box or referenced in order for it to be passed to a function with a Sized constraint.

macro_rules! comp {
($f: expr) => {
move |g: fn(_) -> _| move |x: _| $f(g(x))
};
}
fn main() {
let add1 = |x| x + 1;
let add2 = |x| x + 2;
let add3 = comp!(add1)(add2);
println!("{}", add3(3));
}
https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=1c6915d94f7e1e35cf93fb21daceb9ef

Related

Is there a computationally optimal way to determine the number of digits in a range of natural numbers?

Assume the numbers are in base 10 and each subsequent number is 1 more than the previous.
A naïve solution would be:
fn range_digits(start: usize, end: usize) -> usize {
(start..=end).fold(0, |a, b| a + b.to_string().len())
}
Which gives the output 88915 for the inputs 5 for start and 20005 for end.
The best solution I could come up with was:
use std::convert::TryInto;
fn digits(a: usize) -> usize {
((a as f64).log10() as usize) + 1
}
// Present conversions and type casts could be problematic for certain inputs.
fn range_digits(start: usize, end: usize) -> usize {
let (start_digits, end_digits) = (digits(start), digits(end));
if start_digits == end_digits {
(end - start + 1) * start_digits
} else {
let (a, b) = (
10_usize.pow(start_digits.try_into().unwrap()) - 1,
10_usize.pow((end_digits - 1).try_into().unwrap()) as usize,
);
(digits(a + 1)..=digits(b - 1)).fold(0, |acc, elem| {
acc + 9 * elem * 10_usize.pow((elem - 1).try_into().unwrap())
}) + ((a - start + 1) * start_digits)
+ ((end - b + 1) * end_digits)
}
}
But I'm wondering if there's a yet more computationally efficient/optimal solution/formula.
The fastest approach probably is to do this completely with integer arithmetic. Switching between floats and integers is expensive. Here's a simple implementation. I didn't perform any benchmarks on it.
fn digits_in_range(base: usize, range: Range<usize>) -> usize {
let mut result;
let mut power = 1;
let mut current_digits = 0;
while power <= range.start {
power *= base;
current_digits += 1;
}
result = (power - range.start) * current_digits;
while power <= range.end {
let last_power = power;
power *= base;
current_digits += 1;
result += (power - last_power) * current_digits;
}
result -= (power - range.end) * current_digits;
result
}
This takes the number system base as the first argument, and a Range as the second argument. Note that a Range excludes its endpoint, so it's not included in the count. You can change this to RangeInclusive with a small correction to the code if you prefer.
Here is a solution:
Hard-code the number of digits for intervals of the form [0, 10**k - 1];
Using extremely simple integer arithmetic to deduce the value for any interval [a, b].
Below is code assuming 0 <= a <= b < 10**10.
I don't know rust, so this is python; but the algorithm is so simple that I believe the logic of the code is very understandable.
def get_next_power_of_10(n):
v, p = 10, 1
while v <= n:
v *= 10
p += 1
return (v, p)
# d[k] = number of digits in interval [0, 10**k - 1]
d = [1, 10, 190, 2890, 38890, 488890, 5888890, 68888890, 788888890, 8888888890, 98888888890]
def get_number_of_digits_in_0_n(n):
(v, p) = get_next_power_of_10(n)
return d[p] - p * (v - 1 - n)
def get_number_of_digits_in_interval(a, b):
return get_number_of_digits_in_0_n(b) - get_number_of_digits_in_0_n(a-1)

F# - Recursion on list

Input: [x1; x2; ... ; xn]
Output ([x1; x3; ...; xn], [x2; x4; ...; xn], [x3; x5; ...; xn], ....)
What I have so far is:
let rec split = function
| x0 :: x1 :: xs -> (x0::xs) :: split(x1::xs)
| _ -> []
Which yields:
Input: [1;2;3;4;5;6]
Output: [[1; 3; 4; 5; 6]; [2; 4; 5; 6]; [3; 5; 6]; [4; 6]; [5]]
I don't quite see how I can build a tuple of lists recursively.
Any ideas?
I don't know why u want to do this, and if its some sort of exercise/homework I don't want to give you the answer BUT I will give you a hint, best start with something that does something sort of in the right direction.
This code takes a list and in a very unnecesary convoluted way, recursive returns a tuple of three of them.
let rec tripleList : List<'a> -> (List<'a> * List<'a> * List<'a>) =
function
| [] -> ([],[],[])
| (x :: xs) ->
let (tail1,tail2,tail3) = tripleList xs
(x :: tail1,x :: tail2,x :: tail3)
> tripleList [1..10];;
val it : List<int> * List<int> * List<int> =
([1; 2; 3; 4; 5; 6; 7; 8; 9; 10], [1; 2; 3; 4; 5; 6; 7; 8; 9; 10],
[1; 2; 3; 4; 5; 6; 7; 8; 9; 10])
you don't need to do the whole thing as a single function either, you could create 3 functions, 1 that builds each part of the tuple, and then a fourth function that calls the 3 functions to assemble the answer. That may be a simpler place to start.
So a similar sort of thing would be...
let rec tripleList1 : List<'a> -> List<'a> =
function
| [] -> []
| (x :: xs) ->
(x :: tripleList1 xs)
let rec tripleList2 : List<'a> -> List<'a> =
function
| [] -> []
| (x :: xs) ->
(2 * x :: tripleList2 xs)
let rec tripleList3 : List<'a> -> List<'a> =
function
| [] -> []
| (x :: xs) ->
(3 * x :: tripleList3 xs)
let tripleList : List<int> -> (List<int> * List<int> * List<int>) =
fun xs ->
(tripleList1 xs,tripleList2 xs,tripleList3 xs)
I prefer the first approach, but both are perfectively valid, and makes the distinction between the need for recursive functions to create the recusrive data structure List<'a>, whilst the tuple just requires a simple standalone function
so maybe try to write a function that takes.
[1,2,3,4,5,6,7] -> [1,3,5,7]
and then see if you can generalise that, and then assemble the pieces in another function
(note don't be misled by my example, they have the right structure but they fundamentally don't do what you need, you need to filter out values somehow in each part)

F#: multiplication of polynomials

I found this exercise in "Functional Programming Using F#" (4.22.3):
Declare infix F# operators for addition and multiplication of
polynomials in the chosen representation.
f(x) = a0 + a1 * x + a2 * x^2 + ... + an * x^n
The polynomial is reprsented as a list of integer. For example the polynomial f(x) = x^3 + 2 is represented by the list [2; 0; 0; 1]. Now I need a function that takes two lists of integers and returns a list of integers:
// polymul: int list -> int list -> int list
let polymul p q =
???
The authors gave this hint along with the exercise:
The following recursion formula is useful when defining the
multiplication:
0 * Q(x) = 0
(a0+a1*x+...+an*x^n) * Q(x) =
a0 * Q(x) + x * [(a1+a2*x+...+an*x^(n-1)) * Q(x)]
I could not come up with a solution for this exercise. Can anyone help me?
I have a solution. I took the hint and converted it one-to-one into F#. And it worked magically:
// multiplicate a polynomial with a constant
// polymulconst: float -> float list -> float list
let rec polymulconst c = function
| [] -> []
| a::rest -> c*a::polymulconst c rest
// multiplying a polynomial by x
// polymulx: float list -> float list
let polymulx = function
| [] -> []
| lst -> 0.0::lst
// add two polynomials
// polyadd: float int -> float int -> float int
let rec polyadd ps qs =
match (ps, qs) with
| ([], ys) -> ys
| (xs, []) -> xs
| (x::xs, y::ys) -> (x+y)::polyadd xs ys
// polymul: float int -> float int -> float int
let rec polymul qs = function
| [] -> []
| p::ps -> polyadd (polymulconst p qs)
(polymulx (polymul qs ps))
let ( .++. ) p q = polyadd p q
let ( .**. ) p q = polymul p q
I tested the function in the F# REPL:
> let polyA = [1.0; -2.0; 1.0];;
val polyA : float list = [1.0; -2.0; 1.0]
> let polyB = [-4.0; 3.0; 2.0];;
val polyB : float list = [-4.0; 3.0; 2.0]
> polymul polyA polyB;;
val it : float list = [-4.0; 11.0; -8.0; -1.0; 2.0]
> polyA .**. polyB;;
val it : float list = [-4.0; 11.0; -8.0; -1.0; 2.0]
>

How can I correctly return produced sequences in an F# recursive algorithm

As a tutoring exercise I implemented the Knights Tour algorithm in CS and worked fine, after trying to port it to F# I cannot go past the part where I aggregate the resulting sequences of the Knight's path to return to the caller.
The code is this:
let offsets = [|(-2,-1);(-2,1);(-1,-2);(-1,2);(1,-2);(1,2);(2,-1);(2,1)|];
let squareToPair sqr =
(sqr % 8, sqr / 8)
let pairToSquare (col, row) =
row * 8 + col
// Memoizing function taken from Don Syme (http://blogs.msdn.com/b/dsyme/archive/2007/05/31/a-sample-of-the-memoization-pattern-in-f.aspx)
let memoize f =
let cache = ref Map.empty
fun x ->
match (!cache).TryFind(x) with
| Some res -> res
| None ->
let res = f x
cache := (!cache).Add(x,res)
res
let getNextMoves square =
let (col, row) = squareToPair square
offsets
|> Seq.map (fun (colOff, rowOff) -> (col + colOff, row + rowOff))
|> Seq.filter (fun (c, r) -> c >= 0 && c < 8 && r >= 0 && r < 8) // make sure we don't include squares out of the board
|> Seq.map (fun (c, r) -> pairToSquare (c, r))
let getNextMovesMemoized = memoize getNextMoves
let squareToBoard square =
1L <<< square
let squareToBoardMemoized = memoize squareToBoard
let getValidMoves square board =
getNextMovesMemoized square
|> Seq.filter (fun sqr -> ((squareToBoardMemoized sqr) &&& board) = 0L)
// gets all valid moves from a particular square and board state sorted by moves which have less next possible moves
let getValidMovesSorted square board =
getValidMoves square board
|> Seq.sortBy (fun sqr -> (getValidMoves sqr board) |> Seq.length )
let nextMoves = getValidMovesSorted
let sqrToBoard = squareToBoardMemoized
let findPath square =
let board = sqrToBoard square
let rec findPathRec brd sqr sequence = seq {
match brd with
| -1L -> yield sequence
| _ -> for m in nextMoves sqr do yield! findPathRec (brd ||| (sqrToBoard m)) m m::sequence
}
findPathRec board square [square]
let solution = findPath ((4,4) |> pairToSquare) |> Seq.take 1
I am getting the following error:
The type '(int64 -> seq<int>)' is not a type whose values can be enumerated with this syntax, i.e. is not compatible with either seq<_>, IEnumerable<_> or IEnumerable and does not have a GetEnumerator method (using external F# compiler)
I could probably be misunderstanding how this work, but I would expect the results of nextMoves to be seq<_>. Is there a better way of doing this? Am I missing something? Any recommended patterns?
Thanks in advance!
So the problem is that nextMoves has type
val nextMoves : (int -> int64 -> seq<int>)
because it is identical to getValidMovesSorted. You need to supply the board argument
nextMoves is just getValidMovesSorted which takes two arguments (square and board) - now in findPath you only provided one and I guess you wanted to write this
nextMoves sqr board
but then there are more issues in the rest of the code and it's really hard to figure out what you are trying to do
I think you wanted to do something like this:
let findPath square =
let board = sqrToBoard square
let rec findPathRec brd sqr (sequence : int list) =
match brd with
| -1L -> sequence
| _ ->
[
for m in nextMoves sqr board do
yield! findPathRec (brd ||| (sqrToBoard m)) m (m::sequence)
]
this will compile (but will result in an stack-overflow exception)

F# tail call optimization with 2 recursive calls?

As I was writing this function I knew that I wouldn't get tail call optimization. I still haven't come up with a good way of handling this and was hoping someone else might offer suggestions.
I've got a tree:
type Heap<'a> =
| E
| T of int * 'a * Heap<'a> * Heap<'a>
And I want to count how many nodes are in it:
let count h =
let rec count' h acc =
match h with
| E -> 0 + acc
| T(_, value, leftChild, rightChild) ->
let acc = 1 + acc
(count' leftChild acc) + (count' rightChild acc)
count' h 0
This isn't isn't optimized because of the addition of the counts for the child nodes. Any idea of how to make something like this work if the tree has 1 million nodes?
Thanks, Derek
Here is the implementation of count using CPS. It still blew the stack though.
let count h =
let rec count' h acc cont =
match h with
| E -> cont (1 + acc)
| T(_,_,left,right) ->
let f = (fun lc -> count' right lc cont)
count' left acc f
count' h 0 (fun (x: int) -> x)
Maybe I can come up with some way to partition the tree into enough pieces that I can count without blowing the stack?
Someone asked about the code which generates the tree. It is below.
member this.ParallelHeaps threads =
let rand = new Random()
let maxVal = 1000000
let rec heaper i h =
if i < 1 then
h
else
let heap = LeftistHeap.insert (rand.Next(100,2 * maxVal)) h
heaper (i - 1) heap
let heaps = Array.create threads E
printfn "Creating heap of %d elements, with %d threads" maxVal threads
let startTime = DateTime.Now
seq { for i in 0 .. (threads - 1) ->
async { Array.set heaps i (heaper (maxVal / threads) E) }}
|> Async.Parallel
|> Async.RunSynchronously
|> ignore
printfn "Creating %d sub-heaps took %f milliseconds" threads (DateTime.Now - startTime).TotalMilliseconds
let startTime = DateTime.Now
Array.length heaps |> should_ equal threads <| "The size of the heaps array should match the number of threads to process the heaps"
let rec reMerge i h =
match i with
| -1 -> h
| _ ->
printfn "heap[%d].count = %d" i (LeftistHeap.count heaps.[i])
LeftistHeap.merge heaps.[i] (reMerge (i-1) h)
let heap = reMerge (threads-1) E
printfn "Merging %d heaps took %f milliseconds" threads (DateTime.Now - startTime).TotalMilliseconds
printfn "heap min: %d" (LeftistHeap.findMin heap)
LeftistHeap.count heap |> should_ equal maxVal <| "The count of the reMerged heap should equal maxVal"
You can use continuation-passing style (CPS) to solve that problem. See Recursing on Recursion - Continuation Passing by Matthew Podwysocki.
let tree_size_cont tree =
let rec size_acc tree acc cont =
match tree with
| Leaf _ -> cont (1 + acc)
| Node(_, left, right) ->
size_acc left acc (fun left_size ->
size_acc right left_size cont)
size_acc tree 0 (fun x -> x)
Note also that in Debug builds, tail call optimization is disabled. If you don't want to run in Release mode, you can enable the optimization in the project's properties in Visual Studio.
CPS is a good general solution but you might also like to consider explicit use of a stack because it will be faster and is arguably simpler:
let count heap =
let stack = System.Collections.Generic.Stack[heap]
let mutable n = 0
while stack.Count > 0 do
match stack.Pop() with
| E -> ()
| T(_, _, heap1, heap2) ->
n <- n + 1
stack.Push heap1
stack.Push heap2
n

Resources