Why does foldBack not execute the same side-effects that fold does? - f#

I was working through the answers to Example of the difference between List.fold and List.foldBack trying to get my head around the difference between fold and foldBack. I understand the difference in application order now, but there's a difference in side-effects that I don't understand.
I used List.fold and List.foldBack for my testing. My accumulator functions that were basically equivalent to ::, so that accumulation order would matter. The accumulator functions I used were as follows:
let f acc x =
// printfn "Folding %A into %A" x acc // Side-effect!
x :: acc
let f2 x acc =
// printfn "Folding %A into %A" x acc // Side-effect!
x :: acc
I understand from the F# reference that:
List.fold f [] [1; 2; 3; 4; 5] = (f (f (f (f (f [] 1) 2) 3) 4) 5)
and:
List.foldBack f2 [] [1; 2; 3; 4; 5] = (f2 1 (f2 2 (f2 3 (f2 4 (f2 5 [])))))
should both return true, and they do. Great, I thought; I understand how it works. But just to make sure, I uncommented the side-effect lines from f and f2 and ran List.fold f and List.foldBack f2 again. Result of List.fold f [] [1; 2; 3; 4; 5] with the printfn line uncommented:
Folding 1 into []
Folding 2 into [1]
Folding 3 into [2; 1]
Folding 4 into [3; 2; 1]
Folding 5 into [4; 3; 2; 1]
val it : bool = true
Result of List.foldBack f2 [] [1; 2; 3; 4; 5] with the printfn line uncommented:
val it : bool = true
I was expecting "Folding N into [list]" to show up in both cases. But List.fold executed the side effects of its accumulator function, and List.foldBack did not.
Why is there a difference in side-effect execution between the two forms of fold?

You have the arguments in the wrong order.
It should be
> List.foldBack f2 [1; 2; 3; 4; 5] [];;
Folding 5 into []
Folding 4 into [5]
Folding 3 into [4; 5]
Folding 2 into [3; 4; 5]
Folding 1 into [2; 3; 4; 5]
val it : int list = [1; 2; 3; 4; 5]

Related

F# removing the first occurrence of an element in a list

I want to remove the first occurrence of a given element in a list that has possible duplicates.
For example, a list with [1; 6; 1]. I only want to remove 1 once and returns the list [6;1]. My current implementation:
let rec remove l x =
match l with
| [] -> []
| h::t when h = x -> t
| h::t -> h::(remove l h)
this works only for lists that the number I am trying to remove is the first element. For a list like [6; 7; 6] if I wanted to remove the number 7 and return [6; 6]. It does not traverse the list and remove 7 with my current implementation. What can I do to traverse the entire list and remove only the first occurrence of an element?
The issue you have is in the last line of your code
let rec remove l x =
match l with
| [] -> []
| h::t when h = x -> t
| h::t -> h::(remove l h)
^^^^^^^^^^^
You want to keep the head h and process the tail t but the code do not do this, referring to h and l, instead of t and x.
The type signature of remove is correctly inferred to 'a list-> 'a -> 'a list but the wrong second argument is used in the last match branch. It is using h rather than x as the element to remove parameter.
The first argument is also incorrect, since referring to l does not change through each recursion. It needs to refer to the latest tail t.
So the last match branch should read:
| h::t -> h::(remove t x)
Here is the full corrected code;
let rec remove l x =
match l with
| [] -> []
| h::t when h = x -> t
| h::t -> h::(remove t x)
I ended up writing the same code you did and it seems to work just fine. I reordered the parameters for better piping. I could also work to make this tail-recursive.
let rec removeFirst elem xs =
match xs with
| [] -> []
| h :: t when elem = h -> t
| h :: t -> h :: (removeFirst elem t)
> removeFirst 2 [1;2;2;1];;
val it: int list = [1; 2; 1]
Tail-call optimized version
let removeFirst elem list =
let rec loop head tail =
match tail with
| [] -> list
| x :: xs when x = elem -> (List.rev head) # xs
| x :: xs -> loop (x::head) xs
loop [] list
removeFirst 1 [1; 2; 3] |> printfn "%A" // [2; 3]
removeFirst 2 [1; 2; 3] |> printfn "%A" // [1; 3]
removeFirst 3 [1; 2; 3] |> printfn "%A" // [1; 2]
removeFirst 4 [1; 2; 3] |> printfn "%A" // [1; 2; 3]
How it works:
We're traversing list keeping visited elements in head and unvisited in tail. Take first element from tail and see if it's equal to elem we're searching for. If element is found, reverse head and attach to tail without removed element. If element is not found, attach current to head and continue. If we've reached end of list and element isn't found, then return list without modifications.
Example:
Given list of [1; 2; 3; 4; 5] and element 3 iterations will look like this:
head
tail
x
xs
[]
[1; 2; 3; 4; 5]
1
[2; 3; 4; 5]
[1]
[2; 3; 4; 5]
2
[3; 4; 5]
[2; 1]
[3; 4; 5]
3
[4; 5]
At last iteration element is found and all that's remains is to build list: reverse of [2; 1] is [1; 2], attach to [4; 5] and get [1; 2; 4; 5].
Note: head is kept in reverse to improve performance of building it from O(n2) to O(n). Combining head with xs in second branch can be improved from O(head.length*2) to O(head.length) by avoiding usage of rev with # and building result list manually

Type inference with List.fold

I'm having some issues transforming a list of lists again. I have a list of list of ints it looks like this.
val p5PrimeFactorization : int list list =
[[1]; [2]; [3]; [2; 2]; [5]; [3; 2]; [7]; [2; 2; 2]; [3; 3]; [5; 2]; [11];
[3; 2; 2]; [13]; [7; 2]; [5; 3]; [2; 2; 2; 2]; [17]; [3; 3; 2]; [19];
[5; 2; 2]]
Now I want to transform each list into the product of all entries. Now this works
[for n in 2..20 -> primeFactors n 2 []]
|> List.map (List.sum)
But this doesn't..
[for n in 2..20 -> primeFactors n 2 []]
|> List.map (List.fold (fun acc elem -> acc * elem))
It seems the problem is that it infers the type of acc and elem to be of type int list which isn't right. I don't understand why List.sum which basically does the same thing except it returns the sum of all numbers, works, but my folder will not.
In your second example, you haven't specified the initial value for the fold.
You probably meant something like
|> List.map (List.fold (fun acc elem -> acc * elem) 1)

FSharp Compound List

What's the cleanest & simplest way to create this 'compound' list in F#?
Input:
[ 1; 2; 3; 4; 5 ]
Desired Output:
[ [1]; [1;2]; [1;2;3]; [1,2,3,4]; [1;2;3;4;5] ]
There are many ways but I think this is a clean one:
[1;2;3;4;5]
|> List.scan (fun x y -> x # [y]) []
|> List.tail
using List.scan and finally List.tail to omit the first element which is an empty list.
Here's another way interpreting the contents strictly as ints and using list comprehension:
[1; 2; 3; 4; 5] |> List.map(fun n -> [ for i = 1 to n do yield i ])
And you get the same output as above, but if your input is this:
[2; 1; 2] |> List.map(fun n -> [ for i = 1 to n do yield i ])
You get:
[[1; 2]; [1]; [1; 2]]
Which may or may not be what you want.

F# divide sequence up in blocks [duplicate]

I'm trying to learn F# by rewriting some C# algorithms I have into idiomatic F#.
One of the first functions I'm trying to rewrite is a batchesOf where:
[1..17] |> batchesOf 5
Which would split the sequence into batches with a max of five in each, i.e:
[[1; 2; 3; 4; 5]; [6; 7; 8; 9; 10]; [11; 12; 13; 14; 15]; [16; 17]]
My first attempt at doing this is kind of ugly where I've resorted to using a mutable ref object after running into errors trying to use mutable type inside the closure. Using ref is particularly unpleasant since to dereference it you have to use the ! operator which when inside a condition expression can be counter intuitive to some devs who will read it as logical not. Another problem I ran into is where Seq.skip and Seq.take are not like their Linq aliases in that they will throw an error if size exceeds the size of the sequence.
let batchesOf size (sequence: _ seq) : _ list seq =
seq {
let s = ref sequence
while not (!s |> Seq.isEmpty) do
yield !s |> Seq.truncate size |> List.ofSeq
s := System.Linq.Enumerable.Skip(!s, size)
}
Anyway what would be the most elegant/idiomatic way to rewrite this in F#? Keeping the original behaviour but preferably without the ref mutable variable.
Implementing this function using the seq<_> type idiomatically is difficult - the type is inherently mutable, so there is no simple nice functional way. Your version is quite inefficient, because it uses Skip repeatedly on the sequence. A better imperative option would be to use GetEnumerator and just iterate over elements using IEnumerator. You can find various imperative options in this snippet: http://fssnip.net/1o
If you're learning F#, then it is better to try writing the function using F# list type. This way, you can use idiomatic functional style. Then you can write batchesOf using pattern matching with recursion and accumulator argument like this:
let batchesOf size input =
// Inner function that does the actual work.
// 'input' is the remaining part of the list, 'num' is the number of elements
// in a current batch, which is stored in 'batch'. Finally, 'acc' is a list of
// batches (in a reverse order)
let rec loop input num batch acc =
match input with
| [] ->
// We've reached the end - add current batch to the list of all
// batches if it is not empty and return batch (in the right order)
if batch <> [] then (List.rev batch)::acc else acc
|> List.rev
| x::xs when num = size - 1 ->
// We've reached the end of the batch - add the last element
// and add batch to the list of batches.
loop xs 0 [] ((List.rev (x::batch))::acc)
| x::xs ->
// Take one element from the input and add it to the current batch
loop xs (num + 1) (x::batch) acc
loop input 0 [] []
As a footnote, the imperative version can be made a bit nicer using computation expression for working with IEnumerator, but that's not standard and it is quite advanced trick (for example, see http://fssnip.net/37).
A friend asked me this a while back. Here's a recycled answer. This works and is pure:
let batchesOf n =
Seq.mapi (fun i v -> i / n, v) >>
Seq.groupBy fst >>
Seq.map snd >>
Seq.map (Seq.map snd)
Or an impure version:
let batchesOf n =
let i = ref -1
Seq.groupBy (fun _ -> i := !i + 1; !i / n) >> Seq.map snd
These produce a seq<seq<'a>>. If you really must have an 'a list list as in your sample then just add ... |> Seq.map (List.ofSeq) |> List.ofSeq as in:
> [1..17] |> batchesOf 5 |> Seq.map (List.ofSeq) |> List.ofSeq;;
val it : int list list = [[1; 2; 3; 4; 5]; [6; 7; 8; 9; 10]; [11; 12; 13; 14; 15]; [16; 17]]
Hope that helps!
This can be done without recursion if you want
[0..20]
|> Seq.mapi (fun i elem -> (i/size),elem)
|> Seq.groupBy (fun (a,_) -> a)
|> Seq.map (fun (_,se) -> se |> Seq.map (snd));;
val it : seq<seq<int>> =
seq
[seq [0; 1; 2; 3; ...]; seq [5; 6; 7; 8; ...]; seq [10; 11; 12; 13; ...];
seq [15; 16; 17; 18; ...]; ...]
Depending on how you think this may be easier to understand. Tomas' solution is probably more idiomatic F# though
Hurray, we can use List.chunkBySize, Seq.chunkBySize and Array.chunkBySize in F# 4, as mentioned by Brad Collins and Scott Wlaschin.
This isn't perhaps idiomatic but it works:
let batchesOf n l =
let _, _, temp', res' = List.fold (fun (i, n, temp, res) hd ->
if i < n then
(i + 1, n, hd :: temp, res)
else
(1, i, [hd], (List.rev temp) :: res))
(0, n, [], []) l
(List.rev temp') :: res' |> List.rev
Here's a simple implementation for sequences:
let chunks size (items:seq<_>) =
use e = items.GetEnumerator()
let rec loop i acc =
seq {
if i = size then
yield (List.rev acc)
yield! loop 0 []
elif e.MoveNext() then
yield! loop (i+1) (e.Current::acc)
else
yield (List.rev acc)
}
if size = 0 then invalidArg "size" "must be greater than zero"
if Seq.isEmpty items then Seq.empty else loop 0 []
let s = Seq.init 10 id
chunks 3 s
//output: seq [[0; 1; 2]; [3; 4; 5]; [6; 7; 8]; [9]]
My method involves converting the list to an array and recursively chunking the array:
let batchesOf (sz:int) lt =
let arr = List.toArray lt
let rec bite curr =
if (curr + sz - 1 ) >= arr.Length then
[Array.toList arr.[ curr .. (arr.Length - 1)]]
else
let curr1 = curr + sz
(Array.toList (arr.[curr .. (curr + sz - 1)])) :: (bite curr1)
bite 0
batchesOf 5 [1 .. 17]
[[1; 2; 3; 4; 5]; [6; 7; 8; 9; 10]; [11; 12; 13; 14; 15]; [16; 17]]
I found this to be a quite terse solution:
let partition n (stream:seq<_>) = seq {
let enum = stream.GetEnumerator()
let rec collect n partition =
if n = 1 || not (enum.MoveNext()) then
partition
else
collect (n-1) (partition # [enum.Current])
while enum.MoveNext() do
yield collect n [enum.Current]
}
It works on a sequence and produces a sequence. The output sequence consists of lists of n elements from the input sequence.
You can solve your task with analog of Clojure partition library function below:
let partition n step coll =
let rec split ss =
seq {
yield(ss |> Seq.truncate n)
if Seq.length(ss |> Seq.truncate (step+1)) > step then
yield! split <| (ss |> Seq.skip step)
}
split coll
Being used as partition 5 5 it will provide you with sought batchesOf 5 functionality:
[1..17] |> partition 5 5;;
val it : seq<seq<int>> =
seq
[seq [1; 2; 3; 4; ...]; seq [6; 7; 8; 9; ...]; seq [11; 12; 13; 14; ...];
seq [16; 17]]
As a premium by playing with n and step you can use it for slicing overlapping batches aka sliding windows, and even apply to infinite sequences, like below:
Seq.initInfinite(fun x -> x) |> partition 4 1;;
val it : seq<seq<int>> =
seq
[seq [0; 1; 2; 3]; seq [1; 2; 3; 4]; seq [2; 3; 4; 5]; seq [3; 4; 5; 6];
...]
Consider it as a prototype only as it does many redundant evaluations on the source sequence and not likely fit for production purposes.
This version passes all my tests I could think of including ones for lazy evaluation and single sequence evaluation:
let batchIn batchLength sequence =
let padding = seq { for i in 1 .. batchLength -> None }
let wrapped = sequence |> Seq.map Some
Seq.concat [wrapped; padding]
|> Seq.windowed batchLength
|> Seq.mapi (fun i el -> (i, el))
|> Seq.filter (fun t -> fst t % batchLength = 0)
|> Seq.map snd
|> Seq.map (Seq.choose id)
|> Seq.filter (fun el -> not (Seq.isEmpty el))
I am still quite new to F# so if I'm missing anything - please do correct me, it will be greatly appreciated.

F# split sequence into sub lists on every nth element

Say I have a sequence of 100 elements. Every 10th element I want a new list of the previous 10 elements. In this case I will end up with a list of 10 sublists.
Seq.take(10) looks promising, how can I repeatedly call it to return a list of lists?
now there's Seq.chunkBySize available:
[1;2;3;4;5] |> Seq.chunkBySize 2 = seq [[|1; 2|]; [|3; 4|]; [|5|]]
This is not bad:
let splitEach n s =
seq {
let r = ResizeArray<_>()
for x in s do
r.Add(x)
if r.Count = n then
yield r.ToArray()
r.Clear()
if r.Count <> 0 then
yield r.ToArray()
}
let s = splitEach 5 [1..17]
for a in s do
printfn "%A" a
(*
[|1; 2; 3; 4; 5|]
[|6; 7; 8; 9; 10|]
[|11; 12; 13; 14; 15|]
[|16; 17|]
*)
I have an evolution of three solutions. None of them preserves the ordering of the input elements, which is hopefully OK.
My first solution is quite ugly (making use of ref cells):
//[[4; 3; 2; 1; 0]; [9; 8; 7; 6; 5]; [14; 13; 12; 11; 10]; [17; 16; 15]]
let solution1 =
let split s n =
let i = ref 0
let lst = ref []
seq {
for item in s do
if !i = n then
yield !lst
lst := [item]
i := 1
else
lst := item::(!lst)
i := !i+1
yield !lst
} |> Seq.toList
split {0..17} 5
My second solution factors out the use of ref cells in the first solution, but consequently forces the use of direct IEnumerator access (push in one side, pop out the other)!
//[[17; 16; 15]; [14; 13; 12; 11; 10]; [9; 8; 7; 6; 5]; [4; 3; 2; 1; 0]]
let solution2 =
let split (s:seq<_>) n =
let e = s.GetEnumerator()
let rec each lstlst lst i =
if e.MoveNext() |> not then
lst::lstlst
elif i = n then
each (lst::lstlst) [e.Current] 1
else
each lstlst ((e.Current)::lst) (i+1)
each [] [] 0
split {0..17} 5
My third solution is based on the second solution except it "cheats" by taking a list as input instead of a seq, which enables the most elegant solution using pattern matching as Tomas points out is lacking with seq (which is why we were forced to use direct IEnumerator access).
//[[17; 16; 15]; [14; 13; 12; 11; 10]; [9; 8; 7; 6; 5]; [4; 3; 2; 1; 0]]
let solution3 =
let split inputList n =
let rec each inputList lstlst lst i =
match inputList with
| [] -> (lst::lstlst)
| cur::inputList ->
if i = n then
each inputList (lst::lstlst) [cur] 1
else
each inputList lstlst (cur::lst) (i+1)
each inputList [] [] 0
split [0..17] 5
If preserving the ordering of the elements is important, you can use List.rev for this purpose. For example, in solution2, change the last line of the split function to:
each [] [] 0 |> List.rev |> List.map List.rev
Out of the top of my head:
let rec split size list =
if List.length list < size then
[list]
else
(list |> Seq.take size |> Seq.toList) :: (list |> Seq.skip size |> Seq.toList |> split size)
Perhaps this simple pure implementation might be useful:
let splitAt n xs = (Seq.truncate n xs, if Seq.length xs < n then Seq.empty else Seq.skip n xs)
let rec chunk n xs =
if Seq.isEmpty xs then Seq.empty
else
let (ys,zs) = splitAt n xs
Seq.append (Seq.singleton ys) (chunk n zs)
For example:
> chunk 10 [1..100];;
val it : seq<seq<int>> =
seq
[seq [1; 2; 3; 4; ...]; seq [11; 12; 13; 14; ...];
seq [21; 22; 23; 24; ...]; seq [31; 32; 33; 34; ...]; ...]
> chunk 5 [1..12];;
val it : seq<seq<int>> =
seq [seq [1; 2; 3; 4; ...]; seq [6; 7; 8; 9; ...]; seq [11; 12]]
If in doubt, use fold.
let split n = let one, append, empty = Seq.singleton, Seq.append, Seq.empty
Seq.fold (fun (m, cur, acc) x ->
if m = n then (1, one x, append acc (one cur))
else (m+1, append cur (one x), acc))
(0, empty, empty)
>> fun (_, cur, acc) -> append acc (one cur)
This has the advantage of being fully functional, yet touch each element of the input sequence only once(*) (as opposed to the Seq.take + Seq.skip solutions proposed above).
(*) Assuming O(1) Seq.append. I should certainly hope so.
I found this to be easily the fastest:
let windowChunk n xs =
let range = [0 .. Seq.length xs]
Seq.windowed n xs |> Seq.zip range
|> Seq.filter (fun d -> (fst d) % n = 0)
|> Seq.map(fun x -> (snd x))
i.e. window the list, zip with a list of integers, remove all the overlapping elements, and then drop the integer portion of the tuple.
I think that the solution from Brian is probably the most reasonable simple option. A probelm with sequences is that they cannot be easily processed with the usual pattern matching (like functional lists). One option to avoid that would be to use LazyList from F# PowerPack.
Another option is to define a computation builder for working with IEnumerator type. I wrote something like that recently - you can get it here. Then you can write something like:
let splitEach chunkSize (s:seq<_>) =
Enumerator.toSeq (fun () ->
let en = s.GetEnumerator()
let rec loop n acc = iter {
let! item = en
match item with
| Some(item) when n = 1 ->
yield item::acc |> List.rev
yield! loop chunkSize []
| Some(item) ->
yield! loop (n - 1) (item::acc)
| None -> yield acc |> List.rev }
loop chunkSize [] )
This enables using some functional patterns for list processing - most notably, you can write this as a usual recursive function (similar to the one you would write for lists/lazy lists), but it is imperative under the cover (the let! constructo of iter takes the next element and modifies the enumerator).

Resources