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.
Related
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 |.
I have just started learning Haskell and I am trying to write some basic functions in order to get a better understanding of this language.
I want to write a function which takes a list and an Int (N) as argument and returns the element at index N in the list, without using the !! operator or any built-in function.
Here is what I tried :
myHead :: [a] -> a
myHead (x:_) = x
myHead [] = error "head: empty list"
myNth :: [a] -> Int -> a
myNth x i = if i < 0
then error "nth: index can't be negative"
else myNthIterator x i 0
myNthIterator :: [a] -> Int -> Int -> a
myNthIterator [] i n = error "nth: bad index"
myNthIterator (_:x) i n = if i == n
then myHead x
else myNthIterator x i ( n + 1 )
It works but it's shifted to the right. For example myNth [1, 2, 3, 4] 2 would give 4 and not 3.
From what I understand, (_:x) removes the first element of the list and I don't see how to iterate through the list element by element.
Could someone put me on the trail? I find it difficult to find resources for beginners in this language.
We can use Maybe to model whether the index was valid.
nth :: Int -> [a] -> Maybe a
nth 0 (x : _) = Just x
nth n (x : xs) = nth (n - 1) xs
nth _ [] = Nothing
We can pattern match on the index to get our base case, and the list to get the first element and tail.
What you're doing there with (_:x) is called "pattern matching" in case you didn't know. The general pattern for iterating through a list would be (x : xs) where x is head element of the list being matched and xs is the rest of the list. If you use _ you don't remove anything it is still matched to _ which is the convention for saying "I won't use this".
With that you can make a function like this:
myNth :: [a] -> Int -> a
myNth [] _ = error "out of range"
myNth (x : xs) 0 = x
myNth (_ : xs) n = myNth xs (n - 1)
Whenever myNth is called it will go top to bottom over those definitions trying to match the patterns to the input. So when you call myNth [10,11] 1 it won't match the first clause because [10,11] doesn't match an empty list, it won't match the second either because 1 is not 0 and so it will match the third case where it will match the [10,11] on (10 : [11]), therefore _ is 10 and xs is [11] and 1 will be matched as n. Then it calls itself recursively, as myNth [11] 0. Now that will match the second case and it will return x from the match of [11] on (11 : [])
Like 414owen said you can use the Maybe a type to avoid using error.
P.S.: I don't know how beginner you are but I assume you know of the : operator, it prepends an element to a list... If you go more in depth (afaik) every list is actually stored as a sequence of a:(b:(c:(d:(e:[])))) which is equivalent to [a,b,c,d,e] which is equivalent to a:[b,c,d,e] etc.
It works but it's shifted to the right. For example myNth [1, 2, 3, 4] 2 would give 4 and not 3.
myNthIterator (_:x) i n = if i == n
then myHead x
else myNthIterator x i ( n + 1 )
Let us look at myNthIterator [1..4] 1 1
myNthIterator [1..4] 1 1 -- replace [a, b] with (a: (b : []))
== myNthIterator (1 : [2, 3, 4]) 1 1
-- matching with `myNthIterator (_:x) i n` will result in
-- 1 ~ _
-- x ~ [2, 3, 4]
-- i ~ 1
-- n ~ 1
== if 1 == 1 then myHead [2, 3, 4] else myNthIterator [2, 3, 4] 1 (1 + 1)
== myHead [2, 3, 4]
== 2
So (_:x) matching against (1 : [2, 3, 4]) is suspicious. A first step in fixing it is to replace (_:x) by (x:xs).
myNthIterator (x:xs) i n = ...
In our example this would mean x == 1 and xs == [2, 3, 4].
Assume we use a list to represent number reversely, each node is a digit inside the number.
So [1;2;3;4;5] is the number 54321
Now we want to add up two such lists, e.g., adding [1;2] and [3;4], we get [4;6], which is the number 64.
here is my code:
let add l1 l2 =
let rec add_to up acc = function
| [] -> if up = 1 then 1::acc else acc
| hd::tl ->
let s = hd+up in
if s >= 10 then add_to 1 ((s-10)::acc) tl
else List.rev_append tl (s::acc)
and
add_up up acc = function
| [], [] -> if up = 1 then 1::acc else acc
| l, [] | [], l -> (add_to up [] l) # acc
| hd1::tl1, hd2::tl2 ->
let s = hd1+hd2+up in
if s >= 10 then add_up 1 ((s-10)::acc) (tl1, tl2)
else add_up 0 (s::acc) (tl1, tl2)
in
List.rev (add_up 0 [] (l1, l2))
The idea is very simple, just add two hds from two lists, and carry 1 to the next if the sum of two hds are bigger or equal with 10.
However, I think my code does not look beautiful.
we have the redundant part of the logic to solve the carry.
I have to do # on two lists.
Anyone can help me to make it more beautiful?
I think the trick is to generalize. The essence is to add three things, not two.
let sum a b =
let rec isum a b c =
match a, b with
| [], [] -> if c = 0 then [] else [c]
| [], x | x, [] -> isum [0] x c
| ah :: at, bh :: bt ->
let s = ah + bh + c in
(s mod 10) :: isum at bt (s / 10)
in
isum a b 0
This code isn't tail recursive. A tail recursive version will be a little less elegant.
Note: I assume you use [] to represent 0.
i am trying to write a very simple function in haskell to change a value in a list depending on an input as follows
update_game :: [Int] -> Int -> Int -> [Int]
update_game (x:xs) row take_amnt | row == 1 = x - take_amnt:xs
| row == 2 = x : head(xs) - take_amnt : tail(xs)
| row == 3 = x : head(xs) : last(xs) - take_amnt`
the first two cases work fine, however the last case is causing me problems and im not sure why, the errors i get are :
http://i.stack.imgur.com/jpT8b.png
http://i.stack.imgur.com/tlz5t.png
The second argument to : should be a list, but last(xs) - take_amnt apparently yields only a single element. Try
row == 3 = x : head(xs) : [last(xs) - take_amnt]
The second parameter in ":" should be a list, last(xs) - take_amnt gives an element only.
wrap it in "[]" which would be [last(xs) - take_amnt]
last(xs) - take_amnt
is an Int, but the second argument of (:) must be a list, since (:) :: a -> [a] -> [a].
If your lists are always three elements long (but then you should probably use a tuple instead of a list), as it seems, wrapping that in a [ ] would solve it with the correct semantics,
update_game :: [Int] -> Int -> Int -> [Int]
update_game (x:xs) row take_amnt | row == 1 = x - take_amnt:xs
| row == 2 = x : head(xs) - take_amnt : tail(xs)
| row == 3 = x : head(xs) : [last(xs) - take_amnt]
However, it would be better to pattern-match accordingly
update_game [x,y,z] 1 take_amnt = [x - take_amnt, y, z]
update_game [x,y,z] 2 take_amnt = [x, y - take_amnt, z]
update_game [x,y,z] 3 take_amnt = [x, y, z - take_amnt]
update_game _ _ _ = error "Invalid input"
or make it generic without pattern matching
update_game xs index take_amnt = zipWith (-) xs (replicate (index-1) 0 ++ take_amnt : repeat 0)
I'm trying to look for pairs of elements in a list, assuming that they are the only pair in the list, and there are no more than 3 identical consecutive elements.
I have a function that takes in a list, and returns the index of the first element of the pair, if there is any. If not, then it returns -1
searchForPairs xs = searchHelp xs ((genericLength xs) - 1)
where searchHelp xs n
| searchHelp xs 0 = -1 -- no pairs found
| (xs !! n) == (xs !! (n - 1)) = n
| otherwise = searchHelp xs n-1
For some reason, it is returning the error:
Couldn't match expected type `Bool' with actual type `Int'
In the expression: n
In an equation for `searchHelp':
searchHelp xs n
| searchHelp xs 0 = - 1
| (xs !! n) == (xs !! (n - 1)) = n
| otherwise = searchHelp xs n - 1
In an equation for `searchForPairs':
searchForPairs xs
= searchHelp xs ((genericLength xs) - 1)
where
searchHelp xs n
| searchHelp xs 0 = - 1
| (xs !! n) == (xs !! (n - 1)) = n
| otherwise = searchHelp xs n - 1
It seems like it should work. Any ideas why it is not?
#gereeter already explained your errors, I would just like to point out that you should not return -1 in case the answer is not found. Instead, you should return Nothing if there is no answer and Just pos if the answer is pos. This protects you from many kinds of errors.
I couldn't quite grok what you want to do, but from the code, it looks like you're trying to find two consecutive elements in a list that are equal. Instead of using !! to index the list, you can use pattern matching to extract the first two elements of the list, check if they are equal, and continue searching the remainder (including the second element) if they are not. If the list doesn't have at least two elements, you return Nothing
searchForPairs xs = go 0 xs where
go i (x1:xs#(x2:_)) | x1 == x2 = Just i
| otherwise = go (i+1) xs
go _ _ = Nothing
You have two problems. The first is in this line:
| otherwise = searchHelp xs n-1
The compiler interperets this as (searchHelp xs n) - 1, not searchHelp xs (n-1), as you intended. The second problem is in you use of guards:
| searchHelp xs 0 = -1 -- no pairs found
Since searchHelp xs 0 is not a boolean expression (you wanted to use it as a pattern), the compiler rejected it. I can see two easy solutions:
searchForPairs xs = searchHelp xs ((genericLength xs) - 1)
where searchHelp xs n
| n == 0 = -1 -- no pairs found
| (xs !! n) == (xs !! (n - 1)) = n
| otherwise = searchHelp xs (n-1)
and
searchForPairs xs = searchHelp xs ((genericLength xs) - 1)
where
searchHelp xs 0 = -1 -- no pairs found
searchHelp xs n
| (xs !! n) == (xs !! (n - 1)) = n
| otherwise = searchHelp xs (n-1)
Now, unfortunately, although this works, it is terribly inefficient. This is because of your use of !!. In Haskell, lists are linked lists, and so xs !! n will take n steps, instead of 1. This means that the time your function takes is quadratic in the length of the list. To rectify this, you want to loop along the list forward, using pattern matching:
searchForPairs xs = searchHelp xs 0 where
searchHelp (x1 : x2 : xs) pos
| x1 == x2 = pos
| otherwise = searchHelp (x2 : xs) (pos + 1)
searchHelp _ _ = -1
For what it's worth, here is a somewhat idiomatic (and point-free) implementation of what you are trying to do:
searchPairs :: Eq a => [a] -> Maybe Int
searchPairs = interpret . span (uncurry (/=)) . (zip <*> tail)
where
interpret (flag, res) = if null flag then Nothing else Just $ length res
Explanation: zip <*> tail creates a list of pairs of successive elements (using the reader Applicative type class). uncurry (/=) tests if such a pair is made of identical elements. Finally, interpret translates the result in a value of Maybe Int type.