let rec merge = function
| ([], ys) -> ys
| (xs, []) -> xs
| (x::xs, y::ys) -> if x < y then x :: merge (xs, y::ys)
else y :: merge (x::xs, ys)
let rec split = function
| [] -> ([], [])
| [a] -> ([a], [])
| a::b::cs -> let (M,N) = split cs
(a::M, b::N)
let rec mergesort = function
| [] -> []
| L -> let (M, N) = split L
merge (mergesort M, mergesort N)
mergesort [5;3;2;1] // Will throw an error.
I took this code from here StackOverflow Question but when I run the mergesort with a list I get an error:
stdin(192,1): error FS0030: Value restriction. The value 'it' has been inferred to have generic type
val it : '_a list when '_a : comparison
How would I fix this problem? What is the problem? The more information, the better (so I can learn :) )
Your mergesort function is missing a case causing the signature to be inferred by the compiler to be 'a list -> 'b list instead of 'a list -> 'a list which it should be. The reason it should be 'a list -> 'a list is that you're not looking to changing the type of the list in mergesort.
Try changing your mergesort function to this, that should fix the problem:
let rec mergesort = function
| [] -> []
| [a] -> [a]
| L -> let (M, N) = split L
merge (mergesort M, mergesort N)
Another problem with your code however is that neither merge nor split is tail recursive and you will therefore get stack overflow exceptions on large lists (try to call the corrected mergesort like this mergesort [for i in 1000000..-1..1 -> i]).
You can make your split and merge functions tail recursive by using the accumulator pattern
let split list =
let rec aux l acc1 acc2 =
match l with
| [] -> (acc1,acc2)
| [x] -> (x::acc1,acc2)
| x::y::tail ->
aux tail (x::acc1) (y::acc2)
aux list [] []
let merge l1 l2 =
let rec aux l1 l2 result =
match l1, l2 with
| [], [] -> result
| [], h :: t | h :: t, [] -> aux [] t (h :: result)
| h1 :: t1, h2 :: t2 ->
if h1 < h2 then aux t1 l2 (h1 :: result)
else aux l1 t2 (h2 :: result)
List.rev (aux l1 l2 [])
You can read more about the accumulator pattern here; the examples are in lisp but it's a general pattern that works in any language that provides tail call optimization.
Related
Please, how do I make this function return the value of every branch and leaf as a float list? I have tried several methods with Tail recursion but I am not able to return the head I cannot loop through the branch and leaf.
type 'a Tree = | Leaf of 'a | Branch of 'a Tree * 'a Tree
let medianInTree (lst: float Tree) :float list=
let rec medianInTree' (a : float Tree) acc =
match lst with
| Leaf(n) -> n :: acc
| Branch(Leaf(xx), Leaf(xs)) -> xx :: [xs]
| Branch(Leaf(x), Branch(Leaf(xx), Leaf(xs))) ->
let acc = medianInTree'(Leaf(x)) acc
medianInTree' (Branch(Leaf(xx), Leaf(xs))) acc
| Branch(_, _) -> []
medianInTree' lst []
Question: medianInTree (Branch(Leaf(2.0), Branch(Leaf(3.0), Leaf(5.0))))
I want this result: [2.0;3.0;5.0]
using an accumulator, you can do something like this:
let flatten tree =
let rec toList tree acc =
match tree with
| Leaf a -> a :: acc
| Branch(left, right) ->
let acc = toList left acc
toList right acc
toList tree [] |> List.rev
But doing so, the recursive call to process the left branch is not tail recursive.
To insure tail recursion while processing tree structures, you have to use continuations.
let flatten tree =
let rec toList tree cont acc =
match tree with
| Leaf a -> cont (a :: acc)
| Branch(left, right) -> toList left (fun l ->
toList right (fun r ->
cont r) (cont l)) acc
toList tree id [] |> List.rev
Which can be simplified as:
let flatten tree =
let rec toList tree cont acc =
match tree with
| Leaf a -> cont (a :: acc)
| Branch (left, right) -> toList left (toList right cont) acc
toList tree id [] |> List.rev
Your main bug is using match with lst instead of on a. I made it a bit simpler as well.
let medianInTree (lst: float Tree) :float list=
let rec medianInTree' (a : float Tree)=
match a with
| Leaf(n) -> [n]
| Branch(l, r) -> (medianInTree' l) # (medianInTree' r)
medianInTree' lst
I have this function in haskell which I would like to code in F# using native syntax and not the array functions such as map2.
Haskell:
merge [] ys = ys
merge (x:xs) ys = x:merge ys xs
This code merges two lists index-wise like this:
INPUT: [1,2,3,4,5] [11,12,13,14]
OUTPUT: [1,11,2,12,3,13,4,14,5]
I tried doing it in F# and got this but it of course doesn't compile:
let rec mux x y = function
| [] -> []
| x::xs y::ys -> x::y::mux(xs,ys)
I am really struggling to work with two arrays in the pattern matching, thanks for any help you can give.
The Haskell function doesn't actually match on the two parameters. It only matches on the first parameter and takes the second parameter as is.
In F#, you can match on the first argument, and return a function that processes the second argument:
let rec mux = function
| [] -> (function ys -> ys)
| x::xt -> (function ys -> x :: mux ys xt)
But I find it clearer (and I think it's more efficient — at least it is in OCaml) to take in all the arguments at once, then analyze the argument you need to discriminate on:
let rec mux xs ys =
match xs with
| [] -> ys
| x::xt -> x :: mux ys xt
If you wanted to match on both variables, there would be several solutions. You could nest function constructs:
let rec mux = function
| [] -> (function [] -> … | y::yt -> …)
| x::xt -> (function [] -> … | y::yt -> …)
But here again I prefer nesting match constructs:
let rec mux xs ys =
match xs with
| [] -> (match ys with
| [] -> …
| y::yt -> …)
| x::xt -> (match ys with
| [] -> …
| y::yt -> …)
Alternatively, it's often nicer to match on the pair of inputs; it depends how coupled the two inputs are.
let rec mux xs ys =
match xs, ys with
| [], [] -> …
| [], y::yt -> …
| x::xt, [] -> …
| x::xt, y::yt -> …
let rec merge = function
| ([], ys) -> ys
| (xs, []) -> xs
| (x::xs, y::ys) -> if x < y then x :: merge (xs, y::ys)
else y :: merge (x::xs, ys)
let rec split = function
| [] -> ([], [])
| [a] -> ([a], [])
| a::b::cs -> let (M,N) = split cs
(a::M, b::N)
let rec mergesort = function
| [] -> []
| L -> let (M, N) = split L
merge (mergesort M, mergesort N)
mergesort [5;3;2;1] // Will throw an error.
I took this code from here StackOverflow Question but when I run the mergesort with a list I get an error:
stdin(192,1): error FS0030: Value restriction. The value 'it' has been inferred to have generic type
val it : '_a list when '_a : comparison
How would I fix this problem? What is the problem? The more information, the better (so I can learn :) )
Your mergesort function is missing a case causing the signature to be inferred by the compiler to be 'a list -> 'b list instead of 'a list -> 'a list which it should be. The reason it should be 'a list -> 'a list is that you're not looking to changing the type of the list in mergesort.
Try changing your mergesort function to this, that should fix the problem:
let rec mergesort = function
| [] -> []
| [a] -> [a]
| L -> let (M, N) = split L
merge (mergesort M, mergesort N)
Another problem with your code however is that neither merge nor split is tail recursive and you will therefore get stack overflow exceptions on large lists (try to call the corrected mergesort like this mergesort [for i in 1000000..-1..1 -> i]).
You can make your split and merge functions tail recursive by using the accumulator pattern
let split list =
let rec aux l acc1 acc2 =
match l with
| [] -> (acc1,acc2)
| [x] -> (x::acc1,acc2)
| x::y::tail ->
aux tail (x::acc1) (y::acc2)
aux list [] []
let merge l1 l2 =
let rec aux l1 l2 result =
match l1, l2 with
| [], [] -> result
| [], h :: t | h :: t, [] -> aux [] t (h :: result)
| h1 :: t1, h2 :: t2 ->
if h1 < h2 then aux t1 l2 (h1 :: result)
else aux l1 t2 (h2 :: result)
List.rev (aux l1 l2 [])
You can read more about the accumulator pattern here; the examples are in lisp but it's a general pattern that works in any language that provides tail call optimization.
I'm trying to split an F# list into two by taking alternate elements. Here's my attempt:
let split l =
let rec loop l isEven result1 result2 =
match l with
| [] -> result1 result2
| [head::tail] when isEven -> loop tail (not isEven) head::result1 result2
| [head::tail] -> loop tail (not isEven) result1 head::result2
loop l false [] []
That gives me an error:
Program.fs(5,39): error FS0001: Type mismatch. Expecting a
'a
but given a
'b -> 'a list
The resulting type would be infinite when unifying ''a' and ''b -> 'a list'
I don't see how it can be infinite, and I don't understand why it thinks I'm giving it a function from 'b to 'a list. Could somebody tell me where I'm going wrong?
Jack did a good job of explaining what's wrong. Here's an alternate solution that matches two elements at a time. F#'s pattern matching documentation has a lot of great examples.
let split list =
let rec split odd even list =
match list with
| a::b::tail -> split (a::odd) (b::even) tail
| a::tail -> split (a::odd) even tail
| [] -> List.rev odd, List.rev even
split [] [] list
Example output.
printfn "%A" (split [1 .. 10])
System.Console.ReadLine() |> ignore
([1; 3; 5; 7; 9], [2; 4; 6; 8; 10])
Here's a fixed version:
let rec loop l isEven result1 result2 =
match l with
| [] ->
result1, result2
| head :: tail when isEven ->
loop tail (not isEven) (head :: result1) result2
| head :: tail ->
loop tail (not isEven) result1 (head :: result2)
In the first case ([]), I added a comma since the the loop function needs to return the values as a tuple. Without the comma, you're basically treating result1 like a function and applying result2 to it.
The empty list pattern was correct ([]) but in the other cases, you don't use the brackets -- just the cons (::) pattern.
You needed to enclose the head :: result in parenthesis, otherwise F# reads the code as if you wrote this: (loop tail (not isEven) head) :: (result1 result2).
Oh, and if you want the lists you're returning to be in the same order as the original list, you need to use List.rev when you return the lists, like this:
match l with
| [] ->
List.rev result1, List.rev result2
Finally, here's a slightly simplified version of your function -- you don't really need the isEven parameter to make the function work. Instead, you just try to keep the lists the same length:
let rec loop (result1, result2) l =
match l with
| [] ->
List.rev result1, List.rev result2
| hd :: tl ->
if List.length result1 = List.length result2 then
loop (hd :: result1, result2) tl
else
loop (result1, hd :: result2) tl
The simplest solution is not tail recursive but is very comprehensible:
let prepend2 (x, y) (xs, ys) = x::xs, y::ys
let rec split = function
| [] | [_] as xs -> xs, []
| x0::x1::xs -> prepend2 (x0, x1) (split xs)
(I am aware of this question, but it relates to sequences, which is not my problem here)
Given this input (for example):
let testlist =
[
"*text1";
"*text2";
"text3";
"text4";
"*text5";
"*text6";
"*text7"
]
let pred (s:string) = s.StartsWith("*")
I would like to be able to call MyFunc pred testlist and get this output:
[
["*text1";"*text2"];
["*text5";"*text6";"*text7"]
]
This is my current solution, but I don't really like the nested List.revs (ignore the fact that it takes Seq as input)
let shunt pred sq =
let shunter (prevpick, acc) (pick, a) =
match pick, prevpick with
| (true, true) -> (true, (a :: (List.hd acc)) :: (List.tl acc))
| (false, _) -> (false, acc)
| (true, _) -> (true, [a] :: acc)
sq
|> Seq.map (fun a -> (pred a, a))
|> Seq.fold shunter (false, [])
|> snd
|> List.map List.rev
|> List.rev
there is a List.partition function in the F# core library (in case you wanted to implement this just to have it working and not to learn how to write recursive functions yourself). Using this function, you can write this:
> testlist |> List.partition (fun s -> s.StartsWith("*"))
val it : string list * string list =
(["*text1"; "*text2"; "*text5"; "*text6"; "*text7"], ["text3"; "text4"])
Note that this function returns a tuple instead of returning a list of lists. This is a bit different to what you wanted, but if the predicate returns just true or false, then this makes more sense.
The implementation of partition function that returns tuples is also a bit simpler, so it may be useful for learning purposes:
let partition pred list =
// Helper function, which keeps results collected so
// far in 'accumulator' arguments outTrue and outFalse
let rec partitionAux list outTrue outFalse =
match list with
| [] ->
// We need to reverse the results (as we collected
// them in the opposite order!)
List.rev outTrue, List.rev outFalse
// Append element to one of the lists, depending on 'pred'
| x::xs when pred x -> partitionAux xs (x::outTrue) outFalse
| x::xs -> partitionAux xs outTrue (x::outFalse)
// Run the helper function
partitionAux list [] []
Edit: rev-less version using foldBack added below.
Here's some code that uses lists and tail-recursion:
//divides a list L into chunks for which all elements match pred
let divide pred L =
let rec aux buf acc L =
match L,buf with
//no more input and an empty buffer -> return acc
| [],[] -> List.rev acc
//no more input and a non-empty buffer -> return acc + rest of buffer
| [],buf -> List.rev (List.rev buf :: acc)
//found something that matches pred: put it in the buffer and go to next in list
| h::t,buf when pred h -> aux (h::buf) acc t
//found something that doesn't match pred. Continue but don't add an empty buffer to acc
| h::t,[] -> aux [] acc t
//found input that doesn't match pred. Add buffer to acc and continue with an empty buffer
| h::t,buf -> aux [] (List.rev buf :: acc) t
aux [] [] L
usage:
> divide pred testlist;;
val it : string list list =
[["*text1"; "*text2"]; ["*text5"; "*text6"; "*text7"]]
Using a list as data structure for a buffer means that it always needs to be reversed when outputting the contents. This may not be a problem if individual chunks are modestly sized. If speed/efficiency becomes an issue, you could use a Queue<'a> or a `List<'a>' for the buffers, for which appending is fast. But using these data structures instead of lists also means that you lose the powerful list pattern matching. In my opinion, being able to pattern match lists outweighs the presence of a few List.rev calls.
Here's a streaming version that outputs the result one block at a time. This avoids the List.rev on the accumulator in the previous example:
let dividestream pred L =
let rec aux buf L =
seq { match L, buf with
| [],[] -> ()
| [],buf -> yield List.rev buf
| h::t,buf when pred h -> yield! aux (h::buf) t
| h::t,[] -> yield! aux [] t
| h::t,buf -> yield List.rev buf
yield! aux [] t }
aux [] L
This streaming version avoids the List.rev on the accumulator. Using List.foldBack can be used to avoid reversing the accumulated chunks as well.
update: here's a version using foldBack
//divides a list L into chunks for which all elements match pred
let divide2 pred L =
let f x (acc,buf) =
match pred x,buf with
| true,buf -> (acc,x::buf)
| false,[] -> (acc,[])
| false,buf -> (buf::acc,[])
let rest,remainingBuffer = List.foldBack f L ([],[])
match remainingBuffer with
| [] -> rest
| buf -> buf :: rest
Just reverse the list once up front, and then build the structure in order easily:
let Shunt p l =
let mutable r = List.rev l
let mutable result = []
while not r.IsEmpty do
let mutable thisBatch = []
while not r.IsEmpty && not(p r.Head) do
r <- r.Tail
while not r.IsEmpty && p r.Head do
thisBatch <- r.Head :: thisBatch
r <- r.Tail
if not thisBatch.IsEmpty then
result <- thisBatch :: result
result
The outer while deals with each 'batch', and the first inner while skips over any that don't match the predicate, followed by another while that grabs all those that do and stores them in the current batch. If there was anything in this batch (the final one may be empty), prepend it to the final result.
This is an example where I think locally imperative code is simply superior to a purely functional counterpart. The code above is so easy to write and to reason about.
Another version of shunt:
let shunt pred lst =
let rec tWhile pred lst =
match lst with
| [] -> [], []
| hd :: tl when pred hd -> let taken, rest = tWhile pred tl
(hd :: taken), rest
| lst -> [], lst
let rec collect = function
| [] -> []
| lst -> let taken, rest = tWhile pred lst
taken :: (collect (snd (tWhile (fun x -> not (pred x)) rest)))
collect lst
This one avoids List.rev but it's not tail recursive - so only suitable for small lists.
yet another one...
let partition pred lst =
let rec trec xs cont =
match xs with
| [] -> ([],[]) |> cont
| h::t when pred h -> (fun (y,n) -> h::y,n) >> cont |> trec t
| h::t -> (fun (y,n) -> y,h::n) >> cont |> trec t
trec lst id
then we can define shunt:
let shunt pred lst = lst |> partition pred |> (fun (x,y) -> [x;y])