F# Recursive Tree Validation - recursion

This is a somewhat beginner question. I have been trying to validate the following type of FamilyTree. I can't find a simple way to do this. All help would be appreciated.
type BirthYear = int;;
type Tree = Person of BirthYear * Children
and Children = Tree list;;
I want to validate a given family tree such that every Person is older than their Children and furthermore check if the list of Children is sorted in order of their age (eldest first). Preferably done with a function that return a boolean. Something along the lines of this:
let rec validate (Person(x,child)) =
let vali = child |> List.forall (fun (y,_) -> y < x)

I'd do something like this:
let rec checkAges minBirth = function
| Person(b, _) :: t -> b >= minBirth && checkAges b t
| [] -> true
let rec validate (Person(b, c)) =
List.forall validate c && checkAges (b + minParentAge) c
where minParentAge is set to a reasonable minimum age to have children at.
I'd expect checkAges to be the more difficult part here: the function checks whether the first child it sees is younger than the limit it is given, then recursively checks the next child, with the current child's age as the new limit.
Note some techniques:
The function that checks child ages takes the minimum birthday as input; this is used to validate that the parent is old enough for the first child to be reasonable.
List.forall checks a predicate for all items in a list, and early-outs if a predicate is not fulfilled
function is a shorthand to create a function that does pattern matching on its parameter. Therefore, checkAges actually has two arguments.

Here's a very simple solution using a single recursive function. It's not relying on built-in functions like List.forall but I think it's very declarative and (hopefully) easy to follow.
Rule 1: Every Person is older than their Children
Rule 2: List of Children is sorted in order of their age (eldest first)
Code:
let rec isValid = function
| Person ( _ , []) -> true // Person alone without childs -> always valid
| Person (minYear, Person (year, childs) :: brothers) ->
year > minYear && // Validate Rules (either 1 or 2)
isValid (Person (year, childs)) && // Enforce Rule 1
isValid (Person (year, brothers)) // Enforce Rule 2
I personally don't feel List.forall fits well here, it helps to solve a part of the problem but not the whole, so you need to combine it with more stuff (see the other answers) and in the end you can't avoid a recursive function.
List functions are good for lists but for trees I feel recursion more natural unless your tree provides already a way to traverse it.

Here's a way to do it. Perhaps spending some time analyzing how this works will be helpful to you.
let rec check (Person(age, children)) =
match children with
| [] -> true
| Person(eldest, _)::_ ->
Seq.pairwise children |> Seq.forall ((<||) (>))
&& age > eldest
&& List.forall check children

Related

F# define search function

I am new to F# and am having trouble with my code. Its a simple problem to define a function, search, with that take a boolean function and a list and return an index. So for example:
> search (fun x -> x > 10) [ 2; 12; 3; 23; 62; 8; 2 ];;
val it : int = 1
> search (fun s -> s < "horse") [ "pig"; "lion"; "horse"; "cow"; "turkey" ];;
val it : int = 3
What I have as of right now finds the right match but what I cant figure out is how to return a number instead of the rest of the list. I know I'm getting the list instead of a value back because I wrote "if f head then list". What I don't know is what I should put there instead or if what I have is not going to get the result I want.
Below is the code I have written.
let rec search f list =
match list with
| [] -> [-1]
| head::tail ->
if f head then list
else search f tail
Returning a number is easy, you just... return it. Your problem is that you don't have a number to return, because you can't derive it directly from the current state. You have to keep track of the number yourself, using some internal state variable.
When using recursion you change state by calling your function recursively with "modified" arguments. You're already doing that with the list here. To keep internal state in a recursive function you have to introduce another argument, but not expose it outside. You can solve that by using an internal recursive helper function. Here's one that keeps track of the previous item and returns that when it encounters a match:
let search f list =
let rec loop list prev =
match list with
| [] -> None
| head::tail ->
if f head then prev
else loop tail (Some head)
in
loop list None
That's a silly example, but I don't want to just solve your homework for you, because then you wouldn't learn anything. Using this you should be able to figure out how to keep a counter of which position the current item is in, and return that when it matches. Good luck!
You typically define an inner recursive function to help you carry state as you loop, and then call the inner function with an initial state.
let search predicate list =
let rec loop list index =
match list with
| [] -> -1
| head::tail ->
if predicate head then index
else loop tail (index + 1)
loop list 0

Standard ML : Check conditions when iterating a list

i'm studying the programming language Standard ML and i am wondering how i can iterate a list with a check condition.
In other languages we have for loops like :
var input;
for(var i = 0; i < arr.length; i++) {
if(arr[i] == input) {
//you have arrived at your condition...
} else {
//other case
}
}
f.ex
i want to iterate through a list and check if the input variable matches a existing element in the list.
i = 5
xs = [1,5,2,3,6] --> the element matches after one iteration.
fun check i nil = []
| check i (x::xs) = if i=x
then //dowork
else //iterate;
I've gone through many documentations on how to implement this without success.
It would be really helpful if someone could give me some explaining regarding how i can use let val A in B end; inside or outside of if conditions for this kind of work.
how i can iterate a list with a check condition
fun check i nil = []
| check i (x::xs) = if i=x
then //dowork
else //iterate;
i want to iterate through a list and check if the input variable matches a existing element in the list.
I would call this a predicate combinator. It already exists in the standard library and is called List.exists. But you can also make it yourself:
fun exists p [] = false
| exists p (x::xs) = p x orelse exists p xs
This is a simplification of the if-then-else you're attempting, which would look like:
fun exists p [] = false
| exists p (x::xs) = if p x then true else exists p xs
If-then-else isn't really necessary when the result type is a boolean, since orelse, andalso and not are short-circuiting (will not evaluate their second operand if the result can be determined with the first).
Using this List.exists function to check if a list contains a specific element, you have to construct a p that compares the list element with some given value, e.g.:
fun check y xs = List.exists (fn x => ...) xs
This may seem a bit more complicated than simply writing check recursively from scratch,
fun check y [] = false
| check y (x::xs) = ... orelse check y xs
but a solution using higher-order functions is preferred for several reasons.
One is that a seasoned reader will quickly detect what you're doing when seeing List.exists: Ah, you're scanning a list for an element given a predicate. Whereas if your function is explicitly recursive, the reader will have to read the entire recursion scheme: OK, the function doesn't do anything funky, which I'd have known if I'd seen e.g. List.exists.

Ocaml: Equivalence of two lists

New to Ocaml and have been working on a problem I haven't seen answered yet.
I'm working on a function where there is a tuple of 2 lists that are checked for equivalence.
Example:
# equivalence ([1;2],[1;2]);;
- : bool = true
# equivalence ([1;2],[2;1]);;
- : bool = true
# equivalence ([1;2],[1]);;
- : bool = false
Code I have:
let rec equivalent(a,b) = match a, b with
| [], [] -> true
| [], _
| _, [] -> false
| c::cc, d::dd -> if c = d then equivalent(cc,dd) else false;;
I know the problem lies with the last line. I can get a result of true if all elements are in the same order, but out of order it is a result of false. I'm having trouble going through one list to see if the other list has the element. I've tried to use List.nth, .hd, and .tl (not allowed to use .map or .itr) and have also tried to avoid the imperative features of Ocaml. Any suggestions or somewhere I should look? Thanks.
I assume this is some homework where you have to treat lists as poor mans set.
As Bergi mentioned performance wise the best would be to first sort both list and then compare them with your existing code. But that is probably not how you are supposed to solve this.
Assuming the lists are mend to be sets with not duplicate entries then equivalence of a and b means that a contains every element of b and b contains every element of a.
Start by writing a function contains: 'a -> 'a list -> bool that checks if an item is in a list. Next a function contains_all: 'a list -> 'a list -> bool that uses contains to check if every item in the first list is in the second. That then gives you
let equivalence a b = (contains_all a b) && (contains_all b a)
If your lists can contains duplicates then go with sorting the lists first. Anything else is just too impractical.
Note: contains exists as List.mem if you are allowed to use that.

Extract nth element of a tuple

For a list, you can do pattern matching and iterate until the nth element, but for a tuple, how would you grab the nth element?
TL;DR; Stop trying to access directly the n-th element of a t-uple and use a record or an array as they allow random access.
You can grab the n-th element by unpacking the t-uple with value deconstruction, either by a let construct, a match construct or a function definition:
let ivuple = (5, 2, 1, 1)
let squared_sum_let =
let (a,b,c,d) = ivuple in
a*a + b*b + c*c + d*d
let squared_sum_match =
match ivuple with (a,b,c,d) -> a*a + b*b + c*c + d*d
let squared_sum_fun (a,b,c,d) =
a*a + b*b + c*c + d*d
The match-construct has here no virtue over the let-construct, it is just included for the sake of completeness.
Do not use t-uples, Don¹
There are only a few cases where using t-uples to represent a type is the right thing to do. Most of the times, we pick a t-uple because we are too lazy to define a type and we should interpret the problem of accessing the n-th field of a t-uple or iterating over the fields of a t-uple as a serious signal that it is time to switch to a proper type.
There are two natural replacements to t-uples: records and arrays.
When to use records
We can see a record as a t-uple whose entries are labelled; as such, they are definitely the most natural replacement to t-uples if we want to access them directly.
type ivuple = {
a: int;
b: int;
c: int;
d: int;
}
We then access directly the field a of a value x of type ivuple by writing x.a. Note that records are easily copied with modifications, as in let y = { x with d = 0 }. There is no natural way to iterate over the fields of a record, mostly because a record do not need to be homogeneous.
When to use arrays
A large² homogeneous collection of values is adequately represented by an array, which allows direct access, iterating and folding. A possible inconvenience is that the size of an array is not part of its type, but for arrays of fixed size, this is easily circumvented by introducing a private type — or even an abstract type. I described an example of this technique in my answer to the question “OCaml compiler check for vector lengths”.
Note on float boxing
When using floats in t-uples, in records containing only floats and in arrays, these are unboxed. We should therefore not notice any performance modification when changing from one type to the other in our numeric computations.
¹ See the TeXbook.
² Large starts near 4.
Since the length of OCaml tuples is part of the type and hence known (and fixed) at compile time, you get the n-th item by straightforward pattern matching on the tuple. For the same reason, the problem of extracting the n-th element of an "arbitrary-length tuple" cannot occur in practice - such a "tuple" cannot be expressed in OCaml's type system.
You might still not want to write out a pattern every time you need to project a tuple, and nothing prevents you from generating the functions get_1_1...get_i_j... that extract the i-th element from a j-tuple for any possible combination of i and j occuring in your code, e.g.
let get_1_1 (a) = a
let get_1_2 (a,_) = a
let get_2_2 (_,a) = a
let get_1_3 (a,_,_) = a
let get_2_3 (_,a,_) = a
...
Not necessarily pretty, but possible.
Note: Previously I had claimed that OCaml tuples can have at most length 255 and you can simply generate all possible tuple projections once and for all. As #Virgile pointed out in the comments, this is incorrect - tuples can be huge. This means that it is impractical to generate all possible tuple projection functions upfront, hence the restriction "occurring in your code" above.
It's not possible to write such a function in full generality in OCaml. One way to see this is to think about what type the function would have. There are two problems. First, each size of tuple is a different type. So you can't write a function that accesses elements of tuples of different sizes. The second problem is that different elements of a tuple can have different types. Lists don't have either of these problems, which is why you can have List.nth.
If you're willing to work with a fixed size tuple whose elements are all the same type, you can write a function as shown by #user2361830.
Update
If you really have collections of values of the same type that you want to access by index, you should probably be using an array.
here is a function wich return you the string of the ocaml function you need to do that ;) very helpful I use it frequently.
let tup len n =
if n>=0 && n<len then
let rec rep str nn = match nn<1 with
|true ->""
|_->str ^ (rep str (nn-1))in
let txt1 ="let t"^(string_of_int len)^"_"^(string_of_int n)^" tup = match tup with |" ^ (rep "_," n) ^ "a" and
txt2 =","^(rep "_," (len-n-2)) and
txt3 ="->a" in
if n = len-1 then
print_string (txt1^txt3)
else
print_string (txt1^txt2^"_"^txt3)
else raise (Failure "Error") ;;
For example:
tup 8 6;;
return:
let t8_6 tup = match tup with |_,_,_,_,_,_,a,_->a
and of course:
val t8_6 : 'a * 'b * 'c * 'd * 'e * 'f * 'g * 'h -> 'g = <fun>

Traverse a tree recursively and return an un-muted list of all values found? Possible?

I wonder if this is even possible at all as the question suggest.
My problem is that I cannot seem to grasp how to handle the fact that a given input value can have multiple children. The problem is easily solved by using the mutable SortedSet variable as shown below. But I would really like to find out if this is a problem possible to solve with pure recursion and creation of new un-muted lists or similar. I hope my question is clear. I fear I'm ignorant to the easy conclusion that it's not possible.
As you can see bellow the if(true) will return a list but the else will return a list of list. So the code bellow is not in working state.
let someSet = new System.Collections.Generic.SortedSet<string>()
let rec children(value:string,listSoFar) =
printfn "ID: %A" value
someSet.Add(value) works fine of course.
let newList = List.append listSoFar [value]
if(not (hasChildren(value))) then
newList
else
let tmpCollection = database.GetCollection<Collection>("Collection")
let tmpQuery = Query.EQ("Field",BsonValue.Create(value))
let tmpRes = tmpCollection.Find(tmpQuery)
[ for child in tmpRes do
yield children(child.Value,newList) ]
let resultList = children("aParentStartValue",[])
//Or do i need to use someSet values?
Unless the tree is very deeply nested (in which case, this would be inefficient), you can write the code as a recursive F# sequence expression that generates elements using yield and yield!
let rec children (value:string) = seq {
// Produce the current value as the next element of the sequence
yield value
if hasChildren value then
// If it has children, then get all the children
let tmpCollection = database.GetCollection<Collection>("Collection")
let tmpQuery = Query.EQ("Field",BsonValue.Create(value))
let tmpRes = tmpCollection.Find(tmpQuery)
// For each child, generate all its sub-children recursively
// and return all such elements as part of this sequence using 'yield!'
for child in tmpRes do
yield! children child.Value }
// Using 'List.ofSeq' to fully evaluate the lazy sequence
let resultList = List.ofSeq (children "aParentStartValue")
If the tree is more deeply nested, then the situation is a bit more difficult. When iterating over all the children, you'd need to pass the list collected so far to the first children, get the results and then pass the resulting list to the next children (using something like List.fold). But the above is clean and should work in most cases.

Resources