At Uni we were given a challenge of creating a tail recursive addition of Peano numbers using an accumulator. We aren't allowed to use any library function or other functions that we have created, but we are allowed to 'hide' the accumulator in an auxiliary function
Here's the type
type Peano =
| O
| S of Peano
I'm stuck at how to execute the accumulator as it has no operation on the type defined, i.e. the following is not possible
let tailAdd p1 p2 =
let rec aux p1 p2 acc =
match p1, p2 with
| O, _ -> acc
| S v, b -> aux v b (acc + v)
aux p1 p2 O
Help xD
I don't want to give away the answer, since this is a homework problem, but I'll give you a hint: In the case where p1 matches with S v, you know that v = p1 - 1. Therefore, p1 + p2 = v + (p2 + 1). So how do you write p2 + 1 in Peano numbers?
Figured it out
let tailAdd p1 p2 =
let rec aux p1 p2 acc =
match p1, p2 with
| O, O -> acc
| a, S v -> aux v a (S (acc))
| S v, b -> aux v b (S (acc))
aux p1 p2 O
Related
Im getting an error with this function. Im new to f# so I don't fully know what the code is doing, I tried duplicating a function that only takes one parameter to find vowels in a string.
let rec countDigraph c1 c2 L =
match L with
| [] -> 0
| hd::tl when hd = c1 -> 1 + count c1 tl
| hd::tl when tl = c2 -> 1 + count c2 tl
| _::tl ->0 + countDigraph c1 c2 tl
gets called later in the code:
let printCountDigraph digraph L =
let c1 = List.head digraph
let c2 = List.head digraph
printfn "%A,%A: %A" c1 c2 (countDigraph c1 c2 L)
let digraphs = [['a';'i']; ['c';'h']; ['e';'a']; ['i';'e']; ['o';'u']; ['p';'h']; ['s';'h']; ['t';'h']; ['w';'h'];]
List.iter (fun digraph -> printCountDigraph digraph L) digraphs
In countDigraph, you need to check that the first two characters of the list match the digraph. You seem to be trying to do this by first checking the first one (in the first case) and then the second one (in the second case), but this is not how pattern matching works.
The easiest option is to have a single clause that uses the pattern l1::l2::tl to extract the first two letters, followed by the rest of the list. You need to think whether e.g. eai counts as two digraphs or just one. If two, you need to recursively call countDigraph on c2::tl as below - if just one, you would recursively call countDigraph on just tl.
let rec countDigraph c1 c2 L =
match L with
| [] -> 0
| l1::l2::tl when l1=c1 && l2=c2 -> 1 + countDigraph c1 c2 (c2::tl)
| _::tl ->0 + countDigraph c1 c2 tl
The rest of the code gets much easier if you represent digraphs as a list of pairs, rather than a list of two-element lists:
let printCountDigraph (c1, c2) L =
printfn "%A,%A: %A" c1 c2 (countDigraph c1 c2 L)
let digraphs = [('a','i'); ('c','h'); ('e','a'); ('i','e');
('o','u'); ('p','h'); ('s','h'); ('t','h'); ('w','h')]
let L = List.ofSeq "chai"
List.iter (fun digraph -> printCountDigraph digraph L) digraphs
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 tried to write a tail recursive code for mergesort. The code does compile and run. However, the output is wrong. It only outputs one integer. I was wondering how I would fix this code so that the list of integers are sorted and outputted.
let rec merge L L2 P =
match L, L2 with
| [], [] -> P
| [], _ -> L2
| _, [] -> L
| hd::t1, hd2::t2 ->
if hd <= hd2 then
merge t1 L2 (P # [hd])
else
merge L t2 (P # [hd2])
//
// mergesort:
//
let rec ms L =
match L with
| [] -> []
| e::[] -> L
| _ ->
let mid = List.length L / 2
let (L, L2) = List.splitAt mid L
merge (ms L) (ms L2) []
Your problem is in function merge: imagine you sort the list [2;1]. It turns to merge [2] [1] [], then to merge [] [2] [1], and finally second case of match yields [2]. Second and third cases of match must account for P somehow.
In fact, you absolutely do not need to manipulate 3 lists in your merge, two is quite enough if we refactor it to:
let rec merge l1 l2 =
match (l1,l2) with
| (x,[]) -> x
| ([],y) -> y
| (x::tx,y::ty) ->
if x <= y then x::merge tx l2
else y::merge l1 ty
and change the last line of ms to merge (ms L) (ms L2) - and this variant does work as expected:
ms List<int>.Empty returns []
ms [2;1] returns [1;2]
e.t.c
Update: As #kvb pointed out the merge function above is not tail recursive. This is correct and refactoring it to tail-recursive version requires more involvement by introducing an accumulator acc being filled via continuation function:
let merge l1 l2 =
let rec mergeAux continuation l1 l2 =
match l1, l2 with
| l1, [] -> continuation l1
| [], l2 -> continuation l2
| x::tx, y::ty ->
if x <= y then mergeAux (fun acc -> continuation(x::acc)) tx l2
else mergeAux (fun acc -> continuation(y::acc)) l1 ty
mergeAux id l1 l2
Now the implementation is tail-recursive that is easy to check with:
let rand = System.Random() in
List.init 1000000 (fun _ -> rand.Next(-10000,10000)) |> ms
>
val it : int list =
[-10000; -10000; -10000; -10000; -10000; -10000; -10000; ...
Even after the changes made for the accepted answer you still do not have a tail recursive merge sort. The last line of the merge sort merge (ms L) (ms L2) calls ms twice then calls merge. In order for a function to be tail recursive your function must end with at most one recursive call to itself. This scenario is where continuations are needed. By passing a continuation you can make one call to ms and pass it a continuation that makes the second call to ms and pass that second call another continuation that makes the call to merge. I would actually remove the continuation from the merge function as it is not needed and it makes the merge function more difficult to read than implementing it with an accumulator parameter. Lastly, for easy callability from the outside, I would nest the merge function as well as the ms function inside of a mergeSort function that only takes one list parameter, There's no need to expose the rest of the details to callers. My implementation of a fully tail recursive merge sort in F# would be as follows:
let mergeSort ls =
let rec merge l1 l2 res =
match l1, l2 with
| [], [] -> res |> List.rev
| x::xs, [] -> merge xs [] (x::res)
| [], y::ys -> merge [] ys (y::res)
| x::xs, y::ys when x < y -> merge xs (y::ys) (x::res)
| xs, y::ys -> merge xs ys (y::res)
let rec ms ls cont =
match ls with
| [] -> cont []
| [x] -> cont [x]
| xs ->
let ys, zs = List.splitAt ((List.length xs) / 2) xs
ms ys (fun ys' -> ms zs (fun zs' -> cont (merge ys' zs' [])))
ms ls id
Note that there are ways to do this more efficiently in terms of memory usage, which would likely also help the speed due to less memory allocations, but since that is beyond the scope of this question I'm not going to get into that in the answer.
So I'm sitting with this problem that I can't seem to get my head around in a sensible way. What I'm trying to achieve here is that I have a function descriptionOf os t that takes an Outcome list, os, and a Tree, which ist, and returns a Description using the helper function descriptionOf'. That works quite alright and feeding it with the Outcome list: let outcomeTest = [F;S] and the tree:
let testTree = Branch(">2",0.67, Branch(">3",0.5, Leaf "A", Leaf "B"),Branch(">3",2.5, Leaf "C", Leaf "D")) gives me the following result:
([(F, ">2"); (S, ">3")], 0.825, "C").
Now, as you can see, I've begun making allDescriptions which should take a Tree and return a Set<Description> but I can't the for love of me figure out how to make this set. I've been fiddling with the idea of reusing descriptionOf but the problem the way I see it, is that I don't have an os to give it, but only a tree t. I'm imagining the expected outcome by making the Set<Description> on testTree would be something like this:
set: [([(S,">2");(S,">3")], 0.335, "A"); ([(S,">2");(F,">3")], 0.335, "B");
([(F,">2");(S,">3")], 0.165, "C"); ([(F,">2");(F,">3")], 0.165, "D")].
I hope my question makes sense! Any hints greatly appreciated.
type Outcome = | S | F
type Sample = Outcome list
type Tree = | Branch of string * float * Tree * Tree
| Leaf of string
type Description = ((Sample * string) list * float * string)
let rec descriptionOf' = function
| (os, Branch(ds, p, tl, tr), (dsl, dp, s)) when List.length os > 1 && os.Head = F -> descriptionOf' (os.Tail, tr, (dsl # [(os.Head, ds)], dp * (1.0 - p), ""))
| (os, Branch(ds, p, tl, tr), (dsl, dp, s)) when List.length os > 1 && os.Head = S -> descriptionOf' (os.Tail, tl, (dsl # [(os.Head, ds)], dp * (p), ""))
| (os, Branch(ds, p, Leaf l1, Leaf l2), (dsl, dp, s)) when List.length os = 1 && os.Head = F -> (dsl # [(os.Head, ds)], dp * (1.0 - p), l2)
| (os, Branch(ds, p, Leaf l1, Leaf l2), (dsl, dp, s)) when List.length os = 1 && os.Head = S -> (dsl # [(os.Head, ds)], dp * (p), l1)
| _ -> failwith "Not a correct sample"
let descriptionOf os t =
if isSample(os, t) = false then failwith "Not a correct sample" else
descriptionOf'(os, t, ([], 1.0, ""))
let allDescriptions = Set.empty.Add() // What should this do?
I'm writing a program that takes a polynomial and returns its derivative. The polynomial is passed as predefined type "poly", which is a list of tuples in which the first element is a float representing a coefficient, and the second is an integer representing the degree of that term. So a poly p = [(2.0, 3);(1.5,2);(3.2;1)] would represent 2x^3 + 1.5x^2 + 3.2x^1. My code is as follows:
let rec diff (p:poly):poly =
match p with
| [] -> raise EmptyList
| [a]-> (fst a * snd a, snd a - 1)
| x::xs -> ((fst x * snd x), (snd x - 1)) :: diff xs
The error I'm getting tells me that the program expects the function to return a type poly, but here has the type 'a * 'b. I don't see why thats the case, when in my base case I return a tuple and in all other situations I'm appending onto an accumulating list. I've played around with the brackets, to no avail. Why is my code tossing this error?
All input is appreciated on the matter.
you said it yourself: in the base case you are returning a tuple not a list - so the inference thinks this is what you want
Just change it into:
let rec diff (p:poly):poly =
match p with
| [] -> raise EmptyList
| [a]-> [fst a * snd a, snd a - 1]
| x::xs -> ((fst x * snd x), (snd x - 1)) :: diff xs
and it should be fine (just replace the (..) with [..] ;) )
remember: :: will cons a new head onto a list
there are a few issues with float vs. int there so I would suggest this (using recursion):
type Poly = (float*int) list
let test : Poly = [(2.0, 3);(1.5,2);(3.2,1);(1.0,0)]
let rec diff (p:Poly):Poly =
match p with
| [] -> []
| x::xs -> (fst x * float (snd x), snd x - 1) :: diff xs
which is really just this:
let diff : Poly -> Poly =
List.map (fun x -> fst x * float (snd x), snd x - 1)
and can look a lot nicer without fst and snd:
let diff : Poly -> Poly =
List.map (fun (a,p) -> a * float p, p - 1)