F# Shortening pattern matching on a tree - f#

Not sure if this is the right place for this question, but I have a function, which I'm pretty sure can be simplified, but I'm not sure how.
let rec probOK = function
| Branch(ds, p, Leaf l1, Leaf l2) when p <= 1.0 && p >= 0.0 -> true
| Branch(ds, p, b1, b2) when p <= 1.0 && p >= 0.0 -> probOK b1 && probOK b2
| Branch(ds, p , b1, Leaf l1) when p <= 1.0 && p >= 0.0 -> probOK b1
| Branch(ds, p , Leaf l2, b2) when p <= 1.0 && p >= 0.0 -> probOK b2
| _ -> false
The task is to define a function that takes a probability tree (see below) and check whether it satisfies that every probability p is 0 <= p <= 1. A probability tree has the type
type ProbTree = | Branch of string * float * ProbTree * ProbTree
| Leaf of string
What is meant by probability tree is a tree to represent sample spaces of sequential processes, where the outcomes at each stage in the process is either a success or failure.
An example of a probability tree, where a six-sided die is thrown and the probability that it's >2 is 2/3, the probability it's <= 2 is 1/3 and so on:
In my example, the probability tree I'm working on is:
let test = Branch(">2",0.67, Branch(">3",0.5, Leaf "A", Leaf "B")
, Branch(">3",0.5, Leaf "C", Leaf "D"))
which would return true, as all the probabilities p are within 0 and 1.
Now, the function I've defined works, but I feel like the pattern matching could be simplified, perhaps by doing something akin to ([],Leaf _ )-> true, but I can't quite figure it out.
Any hints?
EDIT1: A shortened suggestion (now with less whitespace):
let rec probOK = function
| Branch(ds, p, b1, b2) when p <= 1.0 && p >= 0.0 -> probOK b1 && probOK b2
| Leaf _ -> true
| _ -> false

You could simplify the code by separating out the traversing of tree nodes from acting on them. Here's a function that checks if a node is valid:
let nodeProbOk = function
| Branch(_, p, _, _)-> p <= 1.0 && p >= 0.0
| Leaf _ -> true
Here's a function that tests that all nodes satisfy a predicate:
let rec forAllNodes pred = function
| Branch(_, _, a, b) as branch -> pred branch && forAllNodes pred a && forAllNodes pred b
| Leaf _ as leaf -> pred leaf
And this is how you would use them together:
test |> forAllNodes nodeProbOk
The advantage of this approach is that you have two relatively simple functions and you can reuse forAllNodes for purposes other than validation. This limits the number of places that you need to use recursion in your code and should make things easier to reason about.

Related

F# Traversing tree to make specific set

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?

How to handle negative power in F#?

I'm trying to build the nth power function in F#. (Yes, there's already Math.Pow in .Net). Here is my attempt:
let rec nthPower x n =
match n with
| 0 -> 1
| _ -> x * (nthPower x (n-1))
This works fine when n >= 0; however, I don't know how to handle the negative case: when n < 0.
Question:
How to handle the negative case? (n<0)
Is this recursive algorithm efficient? or are there any efficient ways in F#?
You can implement it like this:
let rec nthPower x n =
match n with
| 0 -> 1m
| t when t < 0 -> 1m / (nthPower x -n)
| _ -> decimal x * (nthPower x (n - 1));;
The t when t < 0 allows the pattern matching to match a range of values. I would say that the RHS of this line is self-explanatory, but let me know if it's unclear.
Regarding question #2, I don't think there's anything particularly inefficient about this approach and there's probably not a much simpler way to do it. I'm not sure what the most efficient approach is, but hopefully some mathematicians can chime in.
Edit: I have found an approach that is more efficient for exponents > ~10. It uses memoization and divide-and-conquer to compute the result in O(log n) time instead of O(n):
let rec nthPower x n =
match n with
| 0 -> 1.0
| 1 -> double x
| t when t < 0 -> 1.0 / (nthPower x -n)
| _ ->
let p = nthPower x (n / 2)
p * p * nthPower x (n % 2)

Follow sets Top-Down parsing

I have a question for the Follow sets of the following rules:
L -> CL'
L' -> epsilon
| ; L
C -> id:=G
|if GC
|begin L end
I have computed that the Follow(L) is in the Follow(L'). Also Follow(L') is in the Follow(L) so they both will contain: {end, $}. However, as L' is Nullable will the Follow(L) contain also the Follow(C)?
I have computed that the Follow(C) = First(L') and also Follow(C) subset Follow(L) = { ; $ end}.
In the answer the Follow(L) and Follow(L') contain only {end, $}, but shouldn't it contain ; as well from the Follow(C) as L' can be null?
Thanks
However, as L' is Nullable will the Follow(L) contain also the Follow(C)?
The opposite. Follow(C) will contain Follow(L). Think of the following sentence:
...Lx...
where X is some terminal and thus is in Follow(L). This could be expanded to:
...CL'x...
and further to:
...Cx...
So what follows L, can also follow C. The opposite is not necessarily true.
To calculate follows, think of a graph, where the nodes are (NT, n) which means non-terminal NT with the length of tokens as follow (in LL(1), n is either 1 or 0). The graph for yours would look like this:
_______
|/_ \
(L, 1)----->(L', 1) _(C, 1)
| \__________|____________/| |
| | |
| | |
| _______ | |
V |/_ \ V V
(L, 0)----->(L', 0) _(C, 0)
\_______________________/|
Where (X, n)--->(Y, m) means the follows of length n of X, depend on follows of length m of Y (of course, m <= n). That is to calculate (X, n), first you should calculate (Y, m), and then you should look at every rule that contains X on the right hand side and Y on the left hand side e.g.:
Y -> ... X REST
take what REST expands to with length n - m for every m in [0, n) and then concat every result with every follow from the (Y, m) set. You can calculate what REST expands to while calculating the firsts of REST, simply by holding a flag saying whether REST completely expands to that first, or partially. Furthermore, add firsts of REST with length n as follows of X too. For example:
S -> A a b c
A -> B C d
C -> epsilon | e | f g h i
Then to find follows of B with length 3 (which are e d a, d a b and f g h), we look at the rule:
A -> B C d
and we take the sentence C d, and look at what it can produce:
"C d" with length 0 (complete):
"C d" with length 1 (complete):
d
"C d" with length 2 (complete):
e d
"C d" with length 3 (complete or not):
f g h
Now we take these and merge with follow(A, m):
follow(A, 0):
epsilon
follow(A, 1):
a
follow(A, 2):
a b
follow(A, 3):
a b c
"C d" with length 0 (complete) concat follow(A, 3):
"C d" with length 1 (complete) concat follow(A, 2):
d a b
"C d" with length 2 (complete) concat follow(A, 1):
e d a
"C d" with length 3 (complete or not) concat follow(A, 0) (Note: follow(X, 0) is always epsilon):
f g h
Which is the set we were looking for. So in short, the algorithm becomes:
Create the graph of follow dependencies
Find the connected components and create a DAG out of it.
Traverse the DAG from the end (from the nodes that don't have any dependency) and calculate the follows with the algorithm above, having calculated firsts beforehand.
It's worth noting that the above algorithm is for any LL(K). For LL(1), the situation is much simpler.

Usage about Pattern matching

I thought these two function were the same, but it seems that I was wrong.
I define two function f and g in this way:
let rec f n k =
match k with
|_ when (k < 0) || (k > n) -> 0
|_ when k = n -> 100
|_ -> (f n (k+1)) + 1
let rec g n k =
match k with
|_ when (k < 0) || (k > n) -> 0
| n -> 100
|_ -> (g n (k+1)) + 1
let x = f 10 5
let y = g 10 5
The results are:
val x : int = 105
val y : int = 100
Could anyone tell me what's the difference between these two functions?
EDIT
Why does it work here?
let f x =
match x with
| 1 -> 100
| 2 -> 200
|_ -> -1
List.map f [-1..3]
and we get
val f : x:int -> int
val it : int list = [-1; -1; 100; 200; -1]
The difference is that
match k with
...
when k = n -> 100
is a case that matches when some particular condition is true (k = n). The n used in the condition refers to the n that is bound as the function parameter. On the other hand
match k with
...
n -> 100
is a case that only needs to match k against a pattern variable n, which can always succeed. The n in the pattern isn't the same n as the n passed into the function.
For comparison, try the code
let rec g n k =
match k with
|_ when (k < 0) || (k > n) -> 0
| n -> n
|_ -> (g n (k+1)) + 1
and you should see that when you get to the second case, the value returned is the value of the pattern variable n, which has been bound to the value of k.
This behavior is described in the Variable Patterns section of the MSDN F# Language Reference, Pattern Matching:
Variable Patterns
The variable pattern assigns the value being matched to a variable
name, which is then available for use in the execution expression to
the right of the -> symbol. A variable pattern alone matches any
input, but variable patterns often appear within other patterns,
therefore enabling more complex structures such as tuples and arrays
to be decomposed into variables. The following example demonstrates a
variable pattern within a tuple pattern.
let function1 x =
match x with
| (var1, var2) when var1 > var2 -> printfn "%d is greater than %d" var1 var2
| (var1, var2) when var1 < var2 -> printfn "%d is less than %d" var1 var2
| (var1, var2) -> printfn "%d equals %d" var1 var2
function1 (1,2)
function1 (2, 1)
function1 (0, 0)
The use of when is described in more depth in Match Expressions.
The first function is ok, it calls recursively itself n-k times and returns 100 when matches with the conditional where k = n. So, it returns all the calls adding 1 n-k times. with your example, with n=10 and k=5 it is ok the result had been 105.
The problem is the second function. I tested here. See I changed the pattern n->100 to z->100 and it still matches there and never calls itself recursively. So, it always returns 100 if it does not fail in the first conditional. I think F# don't allow that kind of match so it is better to put a conditional to get what you want.

Does F# have loop exit statement?

I know recursive function is a powerful technique in F#. My question is: Is there an exit statement, which can jump out recursive functions, just like imperative languages. For example, Insert a node to a binary tree.
type Tree<'a> when 'a :> IComparable<'a> =
| Nil
| Leaf of 'a
| Node of Tree<'a> * 'a * Tree<'a>
let tt2 = Node(
Node(Leaf "D", "B",Node(Leaf "G", "E", Leaf "H" )),
"A",
Node(Nil, "C", Node(Nil, "F", Leaf "I")))
let rec contains (x : #IComparable<'a>) = function
| Nil -> false
| Leaf y -> if x.CompareTo(y) = 0 then true else false
| Node(l, y, r) ->
match l, y, r with
| l, y, Nil -> if x.CompareTo(y) = 0 then true else contains x l
| Nil,y, r -> if x.CompareTo(y) = 0 then true else contains x r
| _ -> if x.CompareTo(y) = 0 then true
else contains x r |>ignore
contains x l
let xx = contains "C" tt2 //It is wrong answer.
Is there an exit statement, which can jump out recursive functions, just like imperative languages.
No. The very reason is that you can encode imperative break/return by recursive functions and pattern matching. If you would like to break, just return a value, otherwise invoke another recursive call.
This question is more appropriate to ask for high-order functions. When you need early exit on high-order functions, writing custom recursive function is the way to go. If you are interested in imperative constructs in F#, take a look at the excellent series by #Tomas.
Your function will exit at some branch when the condition is determined. The only problem is that you should not discard contain x r in the second to last line.
You can remove superfluous if/else for clarity
let rec contains (x : #IComparable<'a>) = function
| Nil -> false
| Leaf y -> x.CompareTo(y) = 0
| Node(l, y, r) ->
match l, y, r with
| l, y, Nil -> x.CompareTo(y) = 0 || contains x l
| Nil,y, r -> x.CompareTo(y) = 0 || contains x r
| _ -> x.CompareTo(y) = 0 || contains x l || contains x r

Resources