OCaml: Pattern matching vs If/else statements - functional-programming

So, I'm totally new to OCaml and am moving pretty slowly in getting my first functions implemented. One thing I'm having trouble understanding is when to use pattern matching abilities like
let foo =
[] -> true
| _ -> false;;
vs using the if else structure like
let foo a =
if a = [] then true else false;;
When should I use each?

I don't think there's a clear cut answer to that question. First, the obvious case of pattern matching is when you need destructing, e.g.:
let rec sum = function
| [] -> 0
| head :: tail -> head + sum tail;;
Another obvious case is when you're defining a recursive function, pattern matching make the edge condition clearer, e.g.:
let rec factorial = function
| 0 -> 1
| n -> n * factorial(n - 1);;
instead of:
let rec factorial = function n ->
if n = 0 then
1
else
n * factorial(n-1);;
That might not be a great example, just use your imagination to figure out more complex edge conditions! ;-)
In term of regular (say C like) languages, I could say that you should use pattern matching instead of switch/case and if in place of the ternary operator. For everything else it's kind of a grey zone but pattern matching is usually preferred in the ML family of languages.

As far as I know the signifincant difference is that the expression at the guards in the match statement is a pattern which means you can do things that allow you to break apart the shape (destruct) the matched expression, as Nicolas showed in his answer. The other implication of this is that code like this:
let s = 1 in
let x = 2 in
match s with
x -> Printf.printf "x does not equal s!!\n" x
| _ -> Printf.printf "x = %d\n" x;
won't do what you expect. This is because x in the match statement does not refer to the x in the let statement above it but it's a name of the pattern. In cases like these you'd need to use if statements.

For me if..then..else is equivalent to match .. with | true -> .. | false -> .., but there's a syntax sugar if you are facing cases with nested pattern matching, using if..else in an interlace way can help you avoiding to use begin...end to separate different level of patterns
match .. with
| true ->
if .. then
match .. with
| true -> ..
| false -> ..
else
...
| false -> ...
is more compact than
match .. with
| true ->
begin
match .. with
| true ->
begin
match .. with
| true -> ..
| false -> ..
end
| false ->
...
end
| false -> ...

Pattern matching allows for deconstruction of compound data types, and in general, the ability to match pattern within a given data structure, rather than using conditionals like the if.. then structure. Pattern matching can also be used for boolean equality cases using the |x when (r == n) type construct. I should also add pattern matching is a lot more efficient than if... then.. constructs, so use it liberally!

Related

F# Strange difference in behavior of two recursive function definitions

I am trying to define a power function to compute x^y.
let rec powFunA (x,y) =
match (x,y) with
| (_,0) -> 1
| (x,y) -> x * powFunA (x,y-1);;
and
let rec powFunB x y =
match y with
| 0 -> 1
| y -> x * powFunB x y-1;;
The call powFunA (2,5) works and as expected gives me 32 as result. But somehow, I don't understand why, the second call powFunB 2 5 leads to a StackOverflowException.
I also came across a definition:
let rec power = function
| (_,0) -> 1.0 (* 1 *)
| (x,n) -> x * power(x,n-1) (* 2 *)
Can you please explain the absence of parameters and the usage of function on first line of definition.
Thanks.
This stack overflow error has to do with F#'s precedence rules. Consider this expression:
powFunB x y-1
This expression has some function application and the minus operator. In F# (as in all ML languages), function application has the highest precedence ever. Nothing can be more binding.
Therefore, the above expression is understood by the compiler as:
(powFunB x y) - 1
That is, function application powFunB x y first, minus operator second. Now, I hope, it's easy to see why this results in infinite recursion.
To fix, just apply parentheses to override precedence rules:
powFunB x (y-1)
The "parameterless" definition uses F# syntax for defining multicase functions. It's just a shortcut that allows to write = function instead of x = match x with. So, for example, the following two function are equivalent:
let f a = match a with | Some x -> [x] | None -> []
let g = function | Some x -> [x] | None -> []
Just some syntactic sugar, that's all. So the definition you found is exactly equivalent to your first snippet.

Regarding OCaml Pattern Matching Syntax

I am following this OCaml tutorial.
They provided the two functions below and said that they are equivalent.
let string_of_int x = match x with
| 0 -> "zero"
| 1 -> "one"
| 2 -> "two"
| _ -> "many"
let string_of_int2 = function
| 0 -> "zero"
| 1 -> "one"
| 2 -> "two"
| _ -> "many"
My query is regarding the syntax of the above functions.
I wrote the same function but instead of | 0 -> I simply did 0 -> and the function still works in the same way. Is there any particular reason that the tutorial added the extra | in their function?
In the second function what is the use of the function keyword and why was this keyword absent in the first function?
Some people think it looks nicer and more organized, and it allows you to change the order of cases using cut & paste without having to worry about which one didn't have the |.
The function syntax is an abbreviation: function [CASES] is the same as fun x -> match x with [CASES]. There is a subtle difference, which is with function it is not possible to shadow another variable by the name of the parameter.
let string_of_int x = [EXP] is itself an abbreviation for let string_of_int = fun x -> [EXP].
So, to a close approximation, the "canonical" syntax uses fun and match, everything else is sugar. If you apply these two expansions to the two versions of the function, you will see that the same code results (modulo alpha-equivalence, of course :) ).

Default recursion on recursive types

Idiomatic F# can nicely represent the classic recursive expression data structure:
type Expression =
| Number of int
| Add of Expression * Expression
| Multiply of Expression * Expression
| Variable of string
together with recursive functions thereon:
let rec simplify_add (exp: Expression): Expression =
match exp with
| Add (x, Number 0) -> x
| Add (Number 0, x) -> x
| _ -> exp
... oops, that doesn't work as written; simplify_add needs to recur into subexpressions. In this toy example that's easy enough to do, only a couple of extra lines of code, but in a real program there would be dozens of expression types; one would prefer to avoid adding dozens of lines of boilerplate to every function that operates on expressions.
Is there any way to express 'by default, recur on subexpressions'? Something like:
let rec simplify_add (exp: Expression): Expression =
match exp with
| Add (x, Number 0) -> x
| Add (Number 0, x) -> x
| _ -> recur simplify_add exp
where recur might perhaps be some sort of higher-order function that uses reflection to look up the type definition or somesuch?
Unfortunately, F# does not give you any recursive function for processing your data type "for free". You could probably generate one using reflection - this would be valid if you have a lot of recursive types, but it might not be worth it in normal situations.
There are various patterns that you can use to hide the repetition though. One that I find particularly nice is based on the ExprShape module from standard F# libraries. The idea is to define an active pattern that gives you a view of your type as either leaf (with no nested sub-expressions) or node (with a list of sub-expressions):
type ShapeInfo = Shape of Expression
// View expression as a node or leaf. The 'Shape' just stores
// the original expression to keep its original structure
let (|Leaf|Node|) e =
match e with
| Number n -> Leaf(Shape e)
| Add(e1, e2) -> Node(Shape e, [e1; e2])
| Multiply(e1, e2) -> Node(Shape e, [e1; e2])
| Variable s -> Leaf(Shape e)
// Reconstruct an expression from shape, using new list
// of sub-expressions in the node case.
let FromLeaf(Shape e) = e
let FromNode(Shape e, args) =
match e, args with
| Add(_, _), [e1; e2] -> Add(e1, e2)
| Multiply(_, _), [e1; e2] -> Multiply(e1, e2)
| _ -> failwith "Wrong format"
This is some boilerplate code that you'd have to write. But the nice thing is that we can now write the recursive simplifyAdd function using just your special cases and two additional patterns for leaf and node:
let rec simplifyAdd exp =
match exp with
// Special cases for this particular function
| Add (x, Number 0) -> x
| Add (Number 0, x) -> x
// This now captures all other recursive/leaf cases
| Node (n, exps) -> FromNode(n, List.map simplifyAdd exps)
| Leaf _ -> exp

F# recursion with boolean value

So this is the context. Assuming that I have a function that takes a tuple of 2 experiments and test it against a list of rules. The function should stop whenever the tuple of experiments are correctly verified by a certain rule.
type exp = A | B | Mix of exp * exp | Var of string
type sufficency = exp * exp
type rule = Rule of sufficency * (sufficency list)
let rec findout rules (exp1, exp2) = // return a boolean value
match rules with
| [] -> true
| thisRule::remaining ->
match thisRule with
| (suff, condition) ->
match suff with
| (fstExp, sndExp) ->
let map1 = unify Map.empty exp1 fstExp // I don't mention this function in here, but it is defined in my code
let map2 = unify Map.empty exp2 sndExp
true
findout remaining (exp1, exp2)
The problem is, I have no idea how this could be done with functional programming like this. With imperative programming, it would be easier to loop through the list of rules, rather using recursion to go over the list.
So what should the function return at each stage of the recursion?
I got the warning with that code above
warning FS0020: This expression should have type 'unit', but has type
'bool'. Use 'ignore' to discard the result of the expression, or 'let'
to bind the result to a name.
So the problem is in this part of the code
match thisRule with
| (suff, condition) ->
match suff with
| (fstExp, sndExp) ->
let map1 = unify Map.empty exp1 fstExp // I don't mention this function in here, but it is defined in my code
let map2 = unify Map.empty exp2 sndExp
true
findout remaining (exp1, exp2)
The first match returns true so you get a warning. You probably wanted
match thisRule with
| (suff, condition) ->
match suff with
| (fstExp, sndExp) ->
let map1 = unify Map.empty exp1 fstExp // I don't mention this function in here, but it is defined in my code
let map2 = unify Map.empty exp2 sndExp
true && findout remaining (exp1, exp2)
Where you carry the true through the calculation. However, this would probably all be simpler if you used the various List.* functions.

Ocaml Pattern Matching Qualms

I'm having a bit of a problem with regards to pattern matching in Ocaml.
Basically, I need to write a function named reversed that accepts a list and checks whether or not it is in reversed order.
So far:
let rec reversed (x:int list):bool =
match x with
| [] -> true
| y::z::tl -> if y < z then false else reversed tl;
| y::[] -> true;;
It works! (to my surprise actually :P) But there is a flaw I can see, that is if there is no more tl, it would not match. Testing this returns true:
reversed [5;4;3;1;2];;
Which is perfectly understandable since there's no more tail and it simply matches to y::[]
How would I fix this?
PS: This is my first day with Ocaml. Sorry if the question is very easy :D
PPS: I am purposely only using Core. (no modules)
PPPS: I understand the case if I'm doing something fundamentally wrong, please do point it out.
The problem in your function is here :
| y::z::tl -> if y < z then false else reversed tl;
Let's look at your list : [5;4;3;1;2]
It is decomposed this way :
| 5::4::[3;1;2]
And you compare 5 and 4, and then call reverted with [3;2;1]. Wich means that the comparaison between 4 and 3 is not done ! (you can try with a list like [5;4;99;98;97], it is the unexpected result that you have).
What you should do is test on z, and then call reverted with the rest of the list. But if you try something like :
| y::z::_ -> if y < z then false else reversed z;
The compilers yells at you, because z is an int (and not an int list anymore). To solve this, you can "reconstruct" the list by adding z in front of tl :
| y::z::tl -> if y < z then false else reversed (z::tl)
Or name the list after y (which contains z) while still extracting z :
| y::(z::_ as tl) -> if y < z then false else reversed tl
As for your guess about the problem, I understand your logic but actually it does not work that way.
[] can be "named" in your decomposition, just as if it was a regular node.
Look at this example, a (bad) function who tests if the end of the list is reached :
let is_end l = match l with
| a -> false
| [] -> true;;
If you try to put that in your interpreter, you should get the following message :
Warning 11: this match case is unused.
That's because [] is already caught in the first match case. You can try with is_end [], it returns false.
The correct way to handle this is how you did it in your code :
let is_end l = match l with
| x::_ -> false
| [] -> true;;
Your program logic is wrong. You want to check if the list is reversed (decreasing?). But your program fails on input
[5;3;4;2;1]
telling you that it is reversed/decreasing. This is because you drop the 3 too early. Your middle clause should be:
| y::z::tl -> if y < z then false else reversed (z::tl);
You should use | y::z::tl -> if y < z then false else reversed (z::tl).
if y > z, you shouldn't drop z from the next round of list because z has not been compared to the next item yet.
Also you don't need ; in that line.
the correct code is
let rec reversed = function
| [] -> true
| hd::[] -> true
| hd1::hd2::tl ->
if hd1 < hd2 then false
else reversed (hd2::tl)
Here is another way to write it using some other concepts like pattern guards and wild cards:
let rec reversed = function
| [] | [_] -> true
| hd1::hd2::_ when hd1 < hd2 -> false
| _::tl -> reversed tl;;
This way there is one case for true, one for false, and one recursive.

Resources