Folding list of options - f#

Given a list [Some 1; Some 2; Some 3] I would like an output Some 6 . Given a list [Some 1; None] should yield None.
But I'm finding it a bit more difficult than I had imagined to achieve this in a clean way.
The best I could come up with was this
let someNums = [Some 1; Some 2; Some 3]
someNums
|> List.reduce (fun st v ->
Option.bind (fun x ->
Option.map (fun y -> x + y) st) v )

let lift op a b =
match a, b with
| Some av, Some bv -> Some(op av bv)
| _, _ -> None
let plus = lift (+)
[Some 1; Some 2; Some 3]
|> List.reduce plus
// val it : int option = Some 6
[Some 1; None]
|> List.reduce plus
// val it : int option = None
with fold
[Some 1; None]
|> List.fold plus (Some 0)
// val it : int option = None
[Some 1; Some 2; Some 3]
|> List.fold plus (Some 0)
// val it : int option = Some 6
[Some 1; None; Some 2]
|> List.fold plus (Some 0)
// val it : int option = None

You can accomplish this by defining a map2 function for option values:
let optionMap2 f x y =
match x, y with
| (Some x', Some y') -> Some (f x' y')
| _ -> None
This would enable you to write the function you want:
let sumSome = List.fold (optionMap2 (+)) (Some 0)
Example:
> [Some 1; Some 2; Some 3] |> sumSome;;
val it : int option = Some 6
> [Some 1; None; Some 3] |> sumSome;;
val it : int option = None
At the moment, the optionMap2 function isn't available in the F# core library, but probably will be part of the Option module in the future.

Here is an naive implementation of the sequence Gustavo talked about:
let rec sequence =
function
| [] -> Some []
| (Some o :: os) ->
sequence os
|> Option.map (fun os' -> o::os')
| _ -> None
(please note that this is not tail-recursive and not optimized at all so you should transform it if you gonna need it for large lists)
Which would work just as Gustavo told you:
> sequence [Some 1; Some 2; Some 2] |> Option.map List.sum;;
val it : int option = Some 5
> sequence [Some 1; None; Some 2] |> Option.map List.sum;;
val it : int option = None

Related

F# algorithm for hk

Can anyone help me with this problem?
"Realize a function which duplicate each item in a list. You can use List.map"
IN F# sharp language.
And also
"Use the List.init function to generate a list of n random natural numbers between 0 and m."
let makeCopy elem Count =
match Count with
| 0 -> []
| 1 -> elem
let rec dupeElem row count =
match row with
| [] -> []
| hd::tl -> (makeCopy hd count) # dupeElem tl count
//let xs = [1; 2; 3]
//xs |> List.collect (fun x -> List.replicate 3 x)
//val it : int list = [1; 1; 2; 2; 3; 3]
Duplicating the items is pretty straight forward, you just need a recursive function that walks the list.
Generating the random numbers is where you can use List.init to create a new list. You can use the .NET Random class to generate the random numbers you're after.
This gives up the following functions:
let rec duplicateItems list =
match list with
| [] -> []
| head :: tail -> head :: head :: duplicateItems tail
let makeRandomList count upperBound =
let random = Random()
List.init count (fun i -> random.Next(0, upperBound))
You can now generate a random list and pipe it into the duplicate function:
let numbers = makeRandomList 10 20 |> duplicateItems
NOTE: duplicateItems is not tail recursive, so for really large lists this might be an issue. You can get around this by treating the data to duplicate as a sequence:
let duplicateSequence sequence =
seq {
for a in sequence do
yield a
yield a
}
Now we just need to pipe the result into Seq.toList:
let numbers = makeRandomList 10 20 |> duplicateSequence |> Seq.toList
We could also have written makeRandom to return a sequence rather than a list. This would have made the whole computation lazy up until the point we call Seq.toList.
which duplicate each item in a list. You can use List.map
I think your own solution with List.collect is fine. But here's one with List.map:
> let dupe x = List.map (fun s -> [s;s]) x |> List.concat
val dupe : x:'a list -> 'a list
> dupe [1;2;3];;
val it : int list = [1; 1; 2; 2; 3; 3]
Use the List.init function to generate a list of n random natural numbers between 0 and m
I'll show you the general idea, then you can work out the rest, I'm sure. This basically works:
> let rand n max = let r = Random() in List.init n (fun _ -> r.Next(0, max));;
val rand : n:int -> max:int -> int list
> rand 10 12;;
val it : int list = [11; 11; 10; 11; 6; 1; 3; 6; 8; 2]

Replicate list items n times in a F# sequence

I have a sequence in F#:
let n = 2
let seq1 = {
yield "a"
yield "b"
yield "c"
}
I want to print every item in the sequence n times. I can do it this way:
let printx line t =
for i = 1 to t do
printfn "%s" line
seq1 |> Seq.iter (fun i -> printx i n)
Output of this is:
a
a
b
b
c
c
I think this is not the best solution. How to replicate the items in the sequence?
You can create a function to replicate each element of an input sequence:
let replicateAll n s = s |> Seq.collect (fun e -> Seq.init n (fun _ -> e))
then
seq1 |> replicateAll 2 |> Seq.iter (printfn "%s")
I would rather go with a sequence computation expression.
Looks cleaner:
let replicateAll n xs = seq {
for x in xs do
for _ in 1..n do
yield x
}
There is actually a replicate function:
let xs = [1; 2; 3; 4; 5]
xs |> List.collect (fun x -> List.replicate 3 x)
//val it : int list = [1; 1; 1; 2; 2; 2; 3; 3; 3; 4; 4; 4; 5; 5; 5]
And you can do function composition on it, which will get rid of the lambda:
let repCol n xs = (List.replicate >> List.collect) n xs

How can I Implement my own List.partition using tail-recursion?

I'm trying to write my own List.partition function for F# practice. Here's my first (naive) attempt:
let rec mypartition_naive func list =
match list with
| [] -> ([],[])
| head::tail ->
let (h1,h2) = mypartition_naive func tail
if func head
then (head::h1,h2)
else (h1,head::h2)
This works, but it's not tail-recursive. I put together a second attempt that uses an accumulator to become tail-recursive:
let mypartition_accumulator func list =
let rec helper acc listinner =
match listinner with
| head::tail ->
let a,b = acc
let newacc = if func head then (head::a,b) else (a,head::b)
helper newacc tail
| _ -> acc
helper ([],[]) list
Strictly speaking, this works: it partitions the list. The problem is that this reverses the order of the lists. I get this:
let mylist = [1;2;3;4;5;6;7;8]
let partitioned = mypartition_accumulator (fun x -> x % 2 = 0) mynums
//partitioned is now ([8; 6; 4; 2], [7; 5; 3; 1])
//I want partitioned to be ([2; 4; 6; 8], [1; 3; 5; 7])
I think that I can use continuation passing to write a tail-recursive partition function that doesn't reverse the list elements, but I don't really understand continuation passing (and I've read a lot about it). How can I write partition using tail-recursive and keeping the list elements in order?
Here's a CPS version, but List.rev is the way to go (see this related answer).
let partition f list =
let rec aux k = function
| h::t -> aux (fun (a, b) ->
k (if f h then h::a, b else a, h::b)) t
| [] -> k ([], [])
aux id list
Although already answered, this question deserves an attempt at an explanation. The accumulator-based, tail-recursive version is basically fold, left-to-right and hence in need of reversal.
let fold folder state list : 'State =
let rec aux state = function
| [] -> state
| h:'T::t -> aux (folder state h) t
aux state list
// val fold : folder:('State -> 'T -> 'State) -> state:'State -> list:'T list -> 'State
let partitionFold p =
fold (fun (a, b) h -> if p h then h::a, b else a, h::b) ([], [])
>> fun (a, b) -> List.rev a, List.rev b
partitionFold (fun x -> x % 2 = 0) [0..10]
// val it : int list * int list = ([0; 2; 4; 6; 8; 10], [1; 3; 5; 7; 9])
The signature and functionality of fold is now exactly that of List.fold from the standard library.
In contrast, the version in continuation-passing style is equivalent to foldBack (cf. List.foldBack). It iterates recursively from right-to-left (last element first), and thus obtains the desired order right away.
let foldBack folder list state : 'State =
let rec aux k = function
| [] -> k state
| h:'T::t -> aux (folder h >> k) t
aux id list
// val foldBack :
// folder:('T -> 'State -> 'State) -> list:'T list -> state:'State -> 'State
let partitionFoldBack p list =
foldBack (fun h (a, b) -> if p h then h::a, b else a, h::b) list ([], [])
partitionFoldBack (fun x -> x % 2 = 0) [0..10]
// val it : int list * int list = ([0; 2; 4; 6; 8; 10], [1; 3; 5; 7; 9])

Folding a list in F#

I have a pretty trivial task but I can't figure out how to make the solution prettier.
The goal is taking a List and returning results, based on whether they passed a predicate. The results should be grouped. Here's a simplified example:
Predicate: isEven
Inp : [2; 4; 3; 7; 6; 10; 4; 5]
Out: [[^^^^]......[^^^^^^^^]..]
Here's the code I have so far:
let f p ls =
List.foldBack
(fun el (xs, ys) -> if p el then (el::xs, ys) else ([], xs::ys))
ls ([], [])
|> List.Cons // (1)
|> List.filter (not << List.isEmpty) // (2)
let even x = x % 2 = 0
let ret =
[2; 4; 3; 7; 6; 10; 4; 5]
|> f even
// expected [[2; 4]; [6; 10; 4]]
This code does not seem to be readable that much. Also, I don't like lines (1) and (2). Is there any better solution?
Here is my take. you need a few helper functions first:
// active pattern to choose between even and odd intengers
let (|Even|Odd|) x = if (x % 2) = 0 then Even x else Odd x
// fold function to generate a state tupple of current values and accumulated values
let folder (current, result) x =
match x, current with
| Even x, _ -> x::current, result // even members a added to current list
| Odd x, [] -> current, result // odd members are ignored when current is empty
| Odd x, _ -> [], current::result // odd members starts a new current
// test on data
[2; 4; 3; 7; 6; 10; 4; 5]
|> List.rev // reverse list since numbers are added to start of current
|> List.fold folder ([], []) // perform fold over list
|> function | [],x -> x | y,x -> y::x // check that current is List.empty, otherwise add to result
How about this one?
let folder p l = function
| h::t when p(l) -> (l::h)::t
| []::_ as a -> a
| _ as a -> []::a
let f p ls =
ls
|> List.rev
|> List.fold (fun a l -> folder p l a) [[]]
|> List.filter ((<>) [])
At least the folder is crystal clear and effective, but then you pay the price for this by list reversing.
Here is a recursive solution based on a recursive List.filter
let rec _f p ls =
match ls with
|h::t -> if p(h) then
match f p t with
|rh::rt -> (h::rh)::rt
|[] -> (h::[])::[]
else []::f p t
|[] -> [[]]
let f p ls = _f p ls |> List.filter (fun t -> t <> [])
Having to filter at the end does seem inelegant though.
Here you go. This function should also have fairly good performance.
let groupedFilter (predicate : 'T -> bool) (list : 'T list) =
(([], []), list)
||> List.fold (fun (currentGroup, finishedGroups) el ->
if predicate el then
(el :: currentGroup), finishedGroups
else
match currentGroup with
| [] ->
[], finishedGroups
| _ ->
// This is the first non-matching element
// following a matching element.
// Finish processing the previous group then
// add it to the finished groups list.
[], ((List.rev currentGroup) :: finishedGroups))
// Need to do a little clean-up after the fold.
|> fun (currentGroup, finishedGroups) ->
// If the current group is non-empty, finish it
// and add it to the list of finished groups.
let finishedGroups =
match currentGroup with
| [] -> finishedGroups
| _ ->
(List.rev currentGroup) :: finishedGroups
// Reverse the finished groups list so the grouped
// elements will be in their original order.
List.rev finishedGroups;;
With the list reversing, I would like to go to #seq instead of list.
This version uses mutation (gasp!) internally for efficiency, but may also be a little slower with the overhead of seq. I think it is quite readable though.
let f p (ls) = seq {
let l = System.Collections.Generic.List<'a>()
for el in ls do
if p el then
l.Add el
else
if l.Count > 0 then yield l |> List.ofSeq
l.Clear()
if l.Count > 0 then yield l |> List.ofSeq
}
I can't think of a way to do this elegantly using higher order functions, but here's a solution using a list comprehension. I think it's fairly straightforward to read.
let f p ls =
let rec loop xs =
[ match xs with
| [] -> ()
| x::xs when p x ->
let group, rest = collectGroup [x] xs
yield group
yield! loop rest
| _::xs -> yield! loop xs ]
and collectGroup acc = function
| x::xs when p x -> collectGroup (x::acc) xs
| xs -> List.rev acc, xs
loop ls

How do I write a ZipN-like function in F#?

I want to create a function with the signature seq<#seq<'a>> ->seq<seq<'a>> that acts like a Zip method taking a sequence of an arbitrary number of input sequences (instead of 2 or 3 as in Zip2 and Zip3) and returning a sequence of sequences instead of tuples as a result.
That is, given the following input:
[[1;2;3];
[4;5;6];
[7;8;9]]
it will return the result:
[[1;4;7];
[2;5;8];
[3;6;9]]
except with sequences instead of lists.
I am very new to F#, but I have created a function that does what I want, but I know it can be improved. It's not tail recursive and it seems like it could be simpler, but I don't know how yet. I also haven't found a good way to get the signature the way I want (accepting, e.g., an int list list as input) without a second function.
I know this could be implemented using enumerators directly, but I'm interested in doing it in a functional manner.
Here's my code:
let private Tail seq = Seq.skip 1 seq
let private HasLengthNoMoreThan n = Seq.skip n >> Seq.isEmpty
let rec ZipN_core = function
| seqs when seqs |> Seq.isEmpty -> Seq.empty
| seqs when seqs |> Seq.exists Seq.isEmpty -> Seq.empty
| seqs ->
let head = seqs |> Seq.map Seq.head
let tail = seqs |> Seq.map Tail |> ZipN_core
Seq.append (Seq.singleton head) tail
// Required to change the signature of the parameter from seq<seq<'a> to seq<#seq<'a>>
let ZipN seqs = seqs |> Seq.map (fun x -> x |> Seq.map (fun y -> y)) |> ZipN_core
let zipn items = items |> Matrix.Generic.ofSeq |> Matrix.Generic.transpose
Or, if you really want to write it yourself:
let zipn items =
let rec loop items =
seq {
match items with
| [] -> ()
| _ ->
match zipOne ([], []) items with
| Some(xs, rest) ->
yield xs
yield! loop rest
| None -> ()
}
and zipOne (acc, rest) = function
| [] -> Some(List.rev acc, List.rev rest)
| []::_ -> None
| (x::xs)::ys -> zipOne (x::acc, xs::rest) ys
loop items
Since this seems to be the canonical answer for writing a zipn in f#, I wanted to add a "pure" seq solution that preserves laziness and doesn't force us to load our full source sequences in memory at once like the Matrix.transpose function. There are scenarios where this is very important because it's a) faster and b) works with sequences that contain 100s of MBs of data!
This is probably the most un-idiomatic f# code I've written in a while but it gets the job done (and hey, why would there be sequence expressions in f# if you couldn't use them for writing procedural code in a functional language).
let seqdata = seq {
yield Seq.ofList [ 1; 2; 3 ]
yield Seq.ofList [ 4; 5; 6 ]
yield Seq.ofList [ 7; 8; 9 ]
}
let zipnSeq (src:seq<seq<'a>>) = seq {
let enumerators = src |> Seq.map (fun x -> x.GetEnumerator()) |> Seq.toArray
if (enumerators.Length > 0) then
try
while(enumerators |> Array.forall(fun x -> x.MoveNext())) do
yield enumerators |> Array.map( fun x -> x.Current)
finally
enumerators |> Array.iter (fun x -> x.Dispose())
}
zipnSeq seqdata |> Seq.toArray
val it : int [] [] = [|[|1; 4; 7|]; [|2; 5; 8|]; [|3; 6; 9|]|]
By the way, the traditional matrix transpose is much more terse than #Daniel's answer. Though, it requires a list or LazyList that both will eventually have the full sequence in memory.
let rec transpose =
function
| (_ :: _) :: _ as M -> List.map List.head M :: transpose (List.map List.tail M)
| _ -> []
To handle having sub-lists of different lengths, I've used option types to spot if we've run out of elements.
let split = function
| [] -> None, []
| h::t -> Some(h), t
let rec zipN listOfLists =
seq { let splitted = listOfLists |> List.map split
let anyMore = splitted |> Seq.exists (fun (f, _) -> f.IsSome)
if anyMore then
yield splitted |> List.map fst
let rest = splitted |> List.map snd
yield! rest |> zipN }
This would map
let ll = [ [ 1; 2; 3 ];
[ 4; 5; 6 ];
[ 7; 8; 9 ] ]
to
seq
[seq [Some 1; Some 4; Some 7]; seq [Some 2; Some 5; Some 8];
seq [Some 3; Some 6; Some 9]]
and
let ll = [ [ 1; 2; 3 ];
[ 4; 5; 6 ];
[ 7; 8 ] ]
to
seq
[seq [Some 1; Some 4; Some 7]; seq [Some 2; Some 5; Some 8];
seq [Some 3; Some 6; null]]
This takes a different approach to yours, but avoids using some of the operations that you had before (e.g. Seq.skip, Seq.append), which you should be careful with.
I realize that this answer is not very efficient, but I do like its succinctness:
[[1;2;3]; [4;5;6]; [7;8;9]]
|> Seq.collect Seq.indexed
|> Seq.groupBy fst
|> Seq.map (snd >> Seq.map snd);;
Another option:
let zipN ls =
let rec loop (a,b) =
match b with
|l when List.head l = [] -> a
|l ->
let x1,x2 =
(([],[]),l)
||> List.fold (fun acc elem ->
match acc,elem with
|(ah,at),eh::et -> ah#[eh],at#[et]
|_ -> acc)
loop (a#[x1],x2)
loop ([],ls)

Resources