Attempting to compile the following function causes an error:
let balance (left : 'a t) (ele : 'a) (right : 'a t) : 'a t =
match left,ele,right with
| N (d',N (_,a,x,b),y,c),z,d when d' - depth d > 1 && ele < y
| N (d',a,x,N (_,b,y,c)),z,d when d' - depth d > 1 && ele > x
| a,x,N (d',N (_,b,y,c),z,d) when d' - depth a > 1 && ele < z
| a,x,N (d',b,y,N (_,c,z,d)) when d' - depth a > 1 && ele > y
-> new_node (new_node a x b) y (new_node c z d)
| _ -> new_node left ele right
However, both of the following functions will compile without issue:
let balance (left : 'a t) (ele : 'a) (right : 'a t) : 'a t =
match left,ele,right with
| N (d',N (_,a,x,b),y,c),z,d
| N (d',a,x,N (_,b,y,c)),z,d
| a,x,N (d',N (_,b,y,c),z,d)
| a,x,N (d',b,y,N (_,c,z,d))
-> new_node (new_node a x b) y (new_node c z d)
| _ -> new_node left ele right
let balance (left : 'a t) (ele : 'a) (right : 'a t) : 'a t =
match left,ele,right with
| N (d',N (_,a,x,b),y,c),z,d when d' - depth d > 1 && ele < y
-> new_node (new_node a x b) y (new_node c z d)
| _ -> new_node left ele right
How can I get the behavior specified in the first block? Obviously, I could copy the seventh line to each of the preceding patterns, but I'd prefer not to do so.
It's true, this is a limitation of OCaml patterns.
When you write this:
match x with
| 1
| 2 -> f x
You're actually writing just one pattern that looks like this:
match x with
| (1 | 2) -> f x
So this (if it were allowed):
match x with
| 1 when a
| 2 when b -> f x
would be equivalent to something like this:
match x with
| (1 when a | 2) when b -> f x
In other words, what you're trying to do is add when clauses into the middle of a pattern. This isn't supported. They're just a feature of match, not of patterns in general.
As an addendum to what Jeffrey Scofield has already said, beware the following trap.
match 42 with
| 1
| n when n mod 2 = 0 -> "foo"
| n -> "bar"
Or equivalently:
match 42 with
| (1 | n) when n mod 2 = 0 -> "foo"
| n -> "bar"
Both get you this error:
Error: Variable n must occur on both sides of this | pattern
A when conditional guard has to work for either pattern. That's why the following will work.
match (3, 2) with
| (1, n)
| (3, n) when n mod 2 = 0 -> "foo"
| n -> "bar"
Equivalently:
match (3, 2) with
| ((1, n) | (3, n)) when n mod 2 = 0 -> "foo"
| n -> "bar"
Be prepared for compiler warnings if you bind the same name to different values using patterns joined with |.
Related
I am struggling to understand the logic of the code below. I know the code will return a list of Fibonacci numbers from the first till nth e.g. fib 3 will produce [2,1,1,0]. I do not understand how 'n' is split up in (x:y:xs).
I would appreciate any light on this.
Thanks
fib 1 = [1, 0]
fib n = x + y : (x:y:xs)
where (x:y:xs) = fib (n-1)
Your comment about "how" the code splits up the list returned by fib I cannot answer as I don't know all the internals of GHC. This process is called patter matching. In Python and other languages you may be familiar with, this can be done
a, b = (1,2)
# a == 1
# b == 2
Your function is of type
fib :: Int -> [Int]
so you can use pattern matching to extract the head, next head, and next tail of the list it returns, which is what happens in
where (x:y:xs) = fib (n-1)
Perhaps an area of confusion is where the list is being reconstructed so it can be appended to the rest of the list you are returning. Your function can also be written like this
fib 1 = [1, 0]
fib n = x + y : (fib (n-1))
where (x:y:xs) = fib (n-1)
I do not understand how n is split up in (x:y:xs).
n is not being split; the list resulting from fib is being split.
The original code:
fib 1 = [1, 0]
fib n = x + y : (x:y:xs)
where (x:y:xs) = fib (n-1)
Is equivalent to the following, with some of the syntactic sugar removed:
fib n =
if n == 1
then [1, 0]
else case fib (n - 1) of
x : (y : xs) -> (x + y) : (x : (y : xs))
_ -> error "pattern match failure"
Since this code just destructures the list and then rebuilds an identical one, the case branch can also be written using an “as” pattern, e.g.: res#(x : y : xs) -> (x + y) : res
So fib is a function which takes one parameter n, which may be of any numeric type. In the base case when n is 1, the code just returns a constant list [1, 0]. In the recursive case, fib calls itself recursively, replacing n with n - 1. The result will be a list, so the function then pattern-matches on that list to extract its components.
In the pattern x : y : xs, which is syntactic sugar for (:) x ((:) y xs), the operator (:) :: a -> [a] -> [a] is the data constructor for a list that is not empty, and x, y, and xs are variables; so this is equivalent to saying “if the input (the result of fib (n - 1)) is non-empty, then name its head x; and if its tail is non-empty, then name the head and tail of that y and xs respectively”. In other words, if it’s a list of at least two elements, then call the first element x, the second y, and the remainder xs (which may be empty).
In fact it can be implemented in that explicit way, as you’d do in a language that lacks pattern-matching, by using guards or if expressions. The result is quite unwieldy and error-prone, but it may be helpful as an illustration of how to mentally break it down:
fib n
| n == 1
= [1, 0]
| let temp1 = fib (n - 1)
, not (null temp1)
, let x = head temp1
, let temp2 = tail temp1
, not (null temp2)
, let y = head temp2
, let xs = tail temp2
= x + y : temp1
| otherwise
= error "pattern match failure"
fib n =
if n == 1
then [1, 0]
else let
temp1 = fib (n - 1)
in if not (null temp1)
then let
x = head temp1
temp2 = tail temp1
in if not (null temp2)
then let
y = head temp2
xs = tail temp2
in x + y : temp1
else error "pattern match failure"
else error "pattern match failure"
Obviously pattern matching is much simpler!
So here’s an example of how the original code would evaluate on the example input you gave, fib 3:
evaluate: fib 3
matches equation #2 with n₀ = 3: let (x₀ : y₀ : xs₀) = fib (3 - 1) in x₀ + y₀ : (x₀ : y₀ : xs₀)
evaluate: fib 2
matches equation #2 with n₁ = 2: let (x₁ : y₁ : xs₁) = fib (2 - 1) in x₁ + y₁ : (x₁ : y₁ : xs₁)
evaluate: fib 1
matches equation #1: [1, 0]
substitute: let (x₁ : y₁ : xs₁) = 1 : 0 : [] in x₁ + y₁ : (x₁ : y₁ : xs₁)
evaluate let with x₁ = 1, y₁ = 0, xs₁ = []: 1 + 0 : (1 : 0 : [])
substitute: let (x₀ : y₀ : xs₀) = 1 : 1 : [0] in x₀ + y₀ : (x₀ : y₀ : xs₀)
evaluate let with x₀ = 1, y₀ = 1, xs₀ = [0]: 1 + 1 : (1 : 1 : [0])
syntactic sugar for lists: [2, 1, 1, 0]
And a diagram, showing how it builds up a list where each element’s value refers to the subsequent two elements:
┌─────┬───────────┬───────┐ ┌─────┬───────────┬───────────┐ ┌─────┬───┬─────┐ ┌─────┬───┬───┐ ┌────┐
… fib 3───▶ (:) │ (+) x₁ y₁ │ fib 2─┼─▶ (:) │ (+) x₀ y₀ │ xs₁/fib 1─┼─▶ (:) │ 1 │ xs₀─┼─▶ (:) │ 0 │ ○─┼─▶ [] │
└─────┴─────┼──┼──┴───────┘ └─────┴──▲──┼──┼──┴───────────┘ └─────┴─▲─┴─────┘ └─────┴─▲─┴───┘ └────┘
└──┼─────────────────────┘ │ └────────────────────────┼─────────────────┘
└────────────────────────┴───────────────────────────┘
ASCII version:
+-----+-----------+-------+ +-----+-----------+-----------+ +-----+---+-----+ +-----+---+---+ +----+
| | | | | | | | | | | | | | | | | |
… fib 3---> (:) | (+) x1 y1 | fib 2-+---> (:) | (+) x0 y0 | xs1/fib 1-+---> (:) | 1 | xs0-+---> (:) | 0 | o-+---> [] |
| | | | | | | | | | | | | | | | | | | | | |
+-----+-----+--+--+-------+ +-----+--^--+--+--+-----------+ +-----+-^-+-----+ +-----+-^-+---+ +----+
| | | | | | |
+--+-----------------------+ | +--------------------------+-------------------+
| | |
+--------------------------+-----------------------------+
Notice the calls to error: if you try to evaluate a pattern match that isn’t exhaustive, it will throw an exception. In this case, fib will always have at least two elements, so the let binding is safe, but consider how you could change the structure of the code to avoid needing this partial match.
I am using OCaml v 4.00.1. I am trying to write a function using mutual recursion to take a list and return an int. The int is the results of taking alternating elements of the list and adding and subtracting them from each other. For example, the list [1;2;3;4] would results in 1 + 2 - 3 + 4 = 4.
My code is as follows:
let alt list =
let rec add xs = match xs with
[] -> 0
| x::xs -> x + (sub xs)
and sub xs = match xs with
[] -> 0
| x::xs -> x - (add xs);;
OCaml throws a syntax error on the ;; at the very end of the code. I am unsure where to start to figure out what this error actually is.
I suspect you forgot to add in ... portion of the let binding – changes in bold
let alt list =
let rec add xs =
match xs with
| [] -> 0
| x::xs -> x + (sub xs)
and sub xs =
match xs with
| [] -> 0
| x::xs -> x - (add xs)
in
add list
This will start the sequence with +, ie 1 + 2 - 3 ...
If you want it to start with - ...
...
in
sub list
We can swap match syntax for function and readability is improved here
let alt list =
let rec add = function
| [] -> 0
| x::xs -> x + (sub xs)
and sub = function
| [] -> 0
| x::xs -> x - (add xs)
in
add list
I am trying to fill ma lazylist by unpaired elements (with recursion), starting with element k. For example: k = 2, list is [2,3,5,7,9,...] The code:
let lgen =
let rec gen k = LCons(k, fun () -> gen k (k + 2))
in gen 1;;
But how can I check is the element k unpaired? (I think that here I need to use match).
Assuming your type for lazy lists is something like this:
type 'a llist = LNil | LCons of 'a * (unit -> 'a llist);;
You can pattern match like this:
let rec lfind e lxs =
match lxs with
| LNil -> false
| LCons(x, _) when x > e -> false
| LCons(x, xs) -> if e=x then true else lfind e (xs ())
;;
Given the declaration of the swapIfAdjacent function I need to do the following:
swapIfAdjacent :: Eq a => a -> a -> [a] -> [a]
If either a,b or b,a are consecutive items, then for the first and only occurrence the order of these two items should be swapped.
My code so far:
swapIfAdjacent _ _ [] = []
swapIfAdjacent a b (x:xs) | a `elem` xs && b `elem` xs
= if adjacent a b xs then swap a b (x:xs) else (x:xs)
| otherwise = error "not adjacent"
where
swap _ _ [] = []
swap a b (x:xs)
| a == x = b : swap a b xs
| b == x = a : swap a b xs
| otherwise = x : swap a b xs
The adjacent function that I'm using is already defined as follows:
adjacent :: Eq a => a -> a -> [a] -> Bool
adjacent a b (x:y:etc) | x == a
= y == b
| x == b
= y == a
| otherwise
= adjacent a b (y:etc)
adjacent _ _ _ = False
I have observed that according to my implementation the swapping procedure occurs for every element and not only for the first ones and also the following error:
swapIfAdjacent 'a' 'a' "banana" --> banana
while
swapIfAdjacent 'b' 'b' "banana" --> error "not adjacent"
Both of the above examples should produce as output the whole list and not errors. I assume the error has to do with the fact that 'b' is appearing in the list only once "banana" while 'a' multiple times.
You are doing a lot of unnecessary work here. Here's an implementation to consider.
swapIfAdjacent a b (x:y:xys) | (a, b) == (x, y) || (b, a) == (x, y) = y:x:xys
| otherwise = x : swapIfAdjacent a b (y:xys)
swapIfAdjacent _ _ xys = xys
You don't need any of elem, adjacent or swap.
I am hand-writing a parser for a simple regular expression engine.
The engine supports a .. z | * and concatenation and parentheses
Here is the CFG I made:
exp = concat factor1
factor1 = "|" exp | e
concat = term factor2
factor2 = concat | e
term = element factor3
factor3 = * | e
element = (exp) | a .. z
which is equal to
S = T X
X = "|" S | E
T = F Y
Y = T | E
F = U Z
Z = *| E
U = (S) | a .. z
For alternation and closure, I can easily handle them by looking ahead and choose a production based on the token. However, there is no way to handle concatenation by looking ahead cause it is implicit.
I am wondering how can I handle concatenation or is there anything wrong with my grammar?
And this is my OCaml code for parsing:
type regex =
| Closure of regex
| Char of char
| Concatenation of regex * regex
| Alternation of regex * regex
(*| Epsilon*)
exception IllegalExpression of string
type token =
| End
| Alphabet of char
| Star
| LParen
| RParen
| Pipe
let rec parse_S (l : token list) : (regex * token list) =
let (a1, l1) = parse_T l in
let (t, rest) = lookahead l1 in
match t with
| Pipe ->
let (a2, l2) = parse_S rest in
(Alternation (a1, a2), l2)
| _ -> (a1, l1)
and parse_T (l : token list) : (regex * token list) =
let (a1, l1) = parse_F l in
let (t, rest) = lookahead l1 in
match t with
| Alphabet c -> (Concatenation (a1, Char c), rest)
| LParen ->
(let (a, l1) = parse_S rest in
let (t1, l2) = lookahead l1 in
match t1 with
| RParen -> (Concatenation (a1, a), l2)
| _ -> raise (IllegalExpression "Unbalanced parentheses"))
| _ ->
let (a2, rest) = parse_T l1 in
(Concatenation (a1, a2), rest)
and parse_F (l : token list) : (regex * token list) =
let (a1, l1) = parse_U l in
let (t, rest) = lookahead l1 in
match t with
| Star -> (Closure a1, rest)
| _ -> (a1, l1)
and parse_U (l : token list) : (regex * token list) =
let (t, rest) = lookahead l in
match t with
| Alphabet c -> (Char c, rest)
| LParen ->
(let (a, l1) = parse_S rest in
let (t1, l2) = lookahead l1 in
match t1 with
| RParen -> (a, l2)
| _ -> raise (IllegalExpression "Unbalanced parentheses"))
| _ -> raise (IllegalExpression "Unknown token")
For a LL grammar the FIRST sets are the tokens that are allowed as first token for a rule. To can construct them iteratively till you reach a fixed point.
a rule starting with a token has that token in its FIRST set
a rule starting with a term has the FIRST set of that term in its FIRST set
a rule T = A | B has the union of FIRST(A) and FIRST(B) as FIRST set
Start with step 1 and then repeat steps 2 and 3 until the FIRST sets reach a fixed point (don't change). Now you have the true FIRST sets for your grammar and can decide every rule using the lookahead.
Note: In your code the parse_T function doesn't match the FIRST(T) set. If you look at for example 'a|b' then is enters parse_T and the 'a' is matched by the parse_F call. The lookahead then is '|' which matches epsilon in your grammar but not in your code.