Good evening everyone, I'm new to haskell. I'm trying to sum up a list of reading a string Unicode values and store them in a list and then sum the integers up.
getLetterUnicodeValue :: Char -> Int
getLetterUnicodeValue l = (ord l) - 64
unicodeValueList :: String -> [Int]
unicodeValueList x = getLetterUnicodeValue (head x) : unicodeValueList (tail x)
total :: [Int] -> Int
total [] = 0
total x = (head x) + (total (tail x))
I got the error of empty list when the string come to the last character and the sum up function cannot successfully execute. Is there any way to stop the function unicodeValueList when it comes to its end.
*** Exception: Prelude.head: empty list
The surest way to avoid this exception is not to use head. Instead you can use pattern matching to get the head and tail of a list:
unicodeValueList (x:xs) = getLetterUnicodeValue x : unicodeValueList xs
total (x:xs) = x + total xs
This way x and xs will only be available when the list is non-empty and it is guaranteed that you never accidentally access the head or tail of an empty list.
Of course now you'll get a warning that the pattern match is incomplete: You don't specify what should happen when the list is empty. Of course this was true before as well, but now that you use pattern matching the compiler can actually see this and warn you about it (whereas the previous code crashed at runtime without any prior warning).
So what should be done when the list is empty? Well, an empty string contains no unicode values, right? So it should return the empty list when the input is empty:
unicodeValueList [] = []
Of course you don't need pattern matching to fix your error. You could just use an if to make sure that you only call head and tail when the list is not empty. But if you do that, the compiler won't be able to verify that your checks are in order. If you use pattern matching and avoid the unsafe head and tail functions completely, you'll never be able to accidentally access the head or tail of an empty list and the compiler will warn you if you ever forget to consider that the list might be empty.
Yep, you just will have to pattern match in unicodeValueList
unicodeValueList :: String -> [Int]
unicodeValueList [] = []
unicodeValueList (x:xs) = getLetterUnicodeValue x : unicodeValueList xs
Note this could be written more nicely as unicodeValueList = map getLetterUnicodeValue. The reason you are getting the error for head is that your recursion had no base case - it keeps trying to recurse, even when it has reached the empty list.
Related
i try to write a function [int] -> int to count the sum of a list of integers with an iterative function (result should equal the build in function sum)
19>sumList :: [Int] -> Int
20>sumList [list] | length[list] > 0 = [list]!!0 + sumList (drop 1 [list])
21> | otherwise = 0
This is the result if i try to run it
uebung1.lhs:20:2: warning: [-Wincomplete-patterns]
Pattern match(es) are non-exhaustive
In an equation for ‘sumList’:
Patterns not matched:
[]
(_:_:_)
Ok, modules loaded: Main.
*Main> sumList []
*** Exception: uebung1.lhs:(20,2)-(21,31): Non-exhaustive patterns in function sumList
*Main> sumList [3]
*** Exception: uebung1.lhs:(20,2)-(21,31): Non-exhaustive patterns in function sumListi i i i i
What have i done wrong? I've slept a night over it but i just dont see where the problem is. The guarded equations should catch all cases of list lengths. Thanks for any advise.
The problem is that your pattern matches only a list with one element.
For example, if you try to define a function in ghci:
a [x] = x
And then try to call it with the lists with a different number of elements:
a [1] results with 1
a [] results with Exception: <interactive>:5:1-13: Non-exhaustive patterns in function a
a [1,2] results with Exception: <interactive>:1:1-9: Non-exhaustive patterns in function a
The following modification makes your function work:
sumList :: [Int] -> Int
sumList list | length list > 0 = list!!0 + sumList (drop 1 list)
| otherwise = 0
But, certainly, the following definition would be more idiomatic and performant:
sumList :: [Int] -> Int
sumList [] = 0
sumList (x:xs) = x + sumList xs
By (x:xs) pattern you immediately receive x as a head of your list (list!!0) and xs as a tail of it (drop 1 list)
The function will not work for an empty list, or any list with more than one item.
Your problem is that you are matching against [list], a list with one member which is list. Instead, try matching against just list. This means it will match anything of type [Int] from your type signature.
I get your confusion, as the type [a] is for lists of any length, but [a] will only match a list of one element.
I have also attached another way of writing your function using pattern matching, which hopefully you will find useful.
sumList :: [Int] -> Int
sumList [] = 0
sumList (x:xs) = x + sumList xs
It is unusual to use guards, but you did, your code would look like this:
sumList :: [Int] -> Int
sumList list
| length list > 0 = head list + sumList (tail list)
| otherwise = 0
Notice how [list] has been replaced by list, and !! 0 has been replaced by head, and drop 1 has been replaced by tail.
Hoogle is your friend!
You could also move the check for an empty list to the first guard, like so:
sumList :: [Int] -> Int
sumList list
| list == [] = 0
| otherwise = head list + sumList (tail list)
Note how similar this code is to the pattern matching code.
Others have already answered, but I want to stress that the warning emitted by the compiler spotted the issue:
Pattern match(es) are non-exhaustive
In an equation for ‘sumList’:
Patterns not matched:
[]
(_:_:_)
This is saying that the code is not handling some cases in its pattern matching. The empty list [] above is reported as non-matched, meaning that the program will crash on the empty list. Also, the lists of the form (_:_:_) are not matched: these are lists having at least two elements, such as 1:2:rest which is a list starting with elements 1 and 2 and then proceeding with list rest for the next elements.
So, the warning is telling us that we only handle lists of length one. Indeed, we only handle the pattern [_], which is the same of _:[] -- a list starting with one element and then ending there.
If you are a beginner, I think you did not learn pattern matching yet. This should be your priority for learning Haskell: it is one of the most important features. Generally speaking, if your recursive code uses length, !!, tail, head it is very likely that your are doing it wrong. There are some places where these functions are needed, but in many simple exercises they are not, pattern matching being usually sufficient and elegant.
I want to use 'head' function inside map.
The problem is the 'head' function only accepts non-empty list.
I have list of list:
let ll =[["dog", "cat"], ["pig", "cow"], []]
I need to iterate the list of list twice
let listOne = filter(\x -> if length x > 0) ll
map(\x -> head x) listOne
I'm wondering whether I can iterate the list of list once or put a "if condition" inside the map without the 'filter'
Any suggestion would be appreciated.
Yes, in fact you can write it as a list comprehension statement, and use pattern matching instead:
result = [ h | (h:_) <- ll ]
or as a function:
heads :: [[a]] -> [a]
heads ll = [ h | (h:_) <- ll ]
So here we use the pattern (h:_) which matches all non-empty lists, and we directly obtain the head h of such list and add it to the list. If you use a pattern in list comprehension (on the left side of the left arrow <-, it will skip the elements that do not match the pattern).
This is also more safe than using length, since length will get stuck into an infinite loop if you are working with infinite lists. Furthermore by using patterns over the non-total head function, we have more syntactical guarantees that this function will work (yes, once the non-empty elements are filtered, we are of course certain that head will not result in errors, but we only know this because we have information about the head function).
Note that your attempt will result in a syntax error, since you use an if, without a then and else part.
Alternatively, we can, like #DanielWagner says, write the heads function differently, for instance using:
heads :: [[a]] -> [a]
heads ll = concatMap (take 1) ll
or by using the bind of the list monad:
heads :: [[a]] -> [a]
heads = (take 1 =<<)
or we can transpose the 2d list. In that case the first row contains all the heads of the lists. Since it is however not guaranteed that there is such a row, we can append an empty list at the end, like:
heads :: [[a]] -> [a]
heads = head . (++ [[]]) . transpose
I'm new to F# and I'm trying to write a method split that splits a list into 2 pieces. It takes a tuple with the first element being the number of elements to split and the second element is the list . For example, split (2, [1;2;3;4;5;6]) should return ([1;2], [3;4;5;6]),
This is what I have so far, but for some reason it is returning the second element of the tuple as the original list without the head. I don't understand this because I thought that x::xs automatically makes x the head element and xs the rest of the list, which would mean that each recursive call is taking the tail of the previous list and chopping off the first term.
let rec split = function
|(n, []) -> ([], [])
|(0, xs) -> ([], xs)
|(n, x::xs) -> let temp = x :: fst (split(n-1, xs))
(temp, xs);;
The problem is on this line:
(temp,xs);;
here in your example, xs will always be [2;3;4;5;6] as long as n>0
You need to get the second element of the list with something like
|(n,x::xs) ->
let a,b = split (n-1,xs)
(x::a,b)
I'm having trouble with the following exercise :
I'm supposed to reverse all elements in a list except for the first one, the first element of the list must stay in its original position.
Correct Example:
input: rvrsTail [1,2,3,4,5]
output [1,5,4,3,2]
What I have done so far:
rvrsTail :: [x] -> [x]
rvrsTail xs = reverse ( tail xs)
This does reverse the the tail of the list but removes the first element, and since I can't store the first element in a variable I can't seem to understand how to solve this issue.
Erroneous Output:
input: rvrsTail [1,2,3,4,5]
output [5,4,3,2]
Since this is supposed to be a beginner's exercise, the solution should be simple.
When you receive a non-empty list, you must leave the head where it is and append the tail reversed. In other words, you can deconstruct the list into the head and the tail, then reconstruct the list with that head and the reversed tail:
rvrsTail :: [x] -> [x]
rvrsTail [] = []
rvrsTail (listHead : listTail) = listHead : reverse listTail
You are almost there. For making sure that the first element of the list stays as it is, just use pattern matching and remove the tail call:
rvrsTail :: [x] -> [x]
rvrsTail (x:xs) = x:(reverse xs)
Now, note that the above function will throw an exception when tried with empty list. You should handle that case.
Hello All I am trying to flatten a list in Ocaml. I am a newbie so please pardon me if my mistake is dumb
So for example, if input is [[1];[2;3];[4]] I should end up with [1;2;3;4].
The idea I am trying to use is as follows
Iterate through the list from the right (Using fold_right) with accumaltor = []
The pseudo code is as follows
func flatten(list, accumalator)
For each item from right to left in list
If Item is a scalar then n :: accumalator
Else fi Item is a list of form head :: tail then
head :: flatten (tail, accumalator).
I think that theoretically the algorithm is correct, but please let me know if you disagree.
Now to my OCaml code to implement this algorithm
let rec flatten acc x =
match x with
n -> n :: acc
| [x] -> x :: acc
| head :: remainder ->
head :: ( my_flat acc remainder )
and my_flat = List.fold_right flatten
;;
my_flat [] [[1];[2;3];[4]]
The Error I get is the following
Error: This expression has type 'a but an expression was expected of type
'a list
The error occurs on the line that reads head :: ( my_flat acc remainder ) in the last pattern in the match statement
Any help is appreciated.
In OCaml, all the elements of a list must be the same type. Thus the value [1; [2; 3]; 4] is invalid all by itself. It contains two elements that are of type int and one element of type int list. In essence, your statement of the problem to be solved is impossible.
$ ocaml312
Objective Caml version 3.12.0
# [1; [2; 3]; 4];;
Characters 4-10:
[1; [2; 3]; 4];;
^^^^^^
Error: This expression has type 'a list
but an expression was expected of type int
This sounds like a homework problem, so I'll just say that restricting yourself to lists that are valid in OCaml may make it easier to solve.
Edit
OK, the problem can now be solved!
The essence of the reported type error is something like this. You have your accumulated result acc (of type int list in the example). You want to add the list x (also of type int list) to it. You've broken x into head (an int) and remainder (an int list). As you can see, remainder is not a suitable argument for your my_flat function. It wants an int list list, i.e., a list of lists of ints. In fact, your recursive call should almost certainly go to flatten and not to my_flat.
Another problem I see: the arguments of List.fold_right are: a function, a list, and a starting value. In your test call to my_flat, you're supplying the last two in the other order. The empty list [] is your starting value.
I hope this is enough to get you going. Since you're just starting out with OCaml there will probably be another problem or two before it works.
Edit 2
Here are a couple more comments, which might be spoilers if you're still working on your own solution....
A tidier version of your function my_flat is in the OCaml standard library under the name List.flatten. It's interesting to look at the implementation:
let rec flatten = function
[] -> []
| l::r -> l # flatten r
I'd call this a very elegant solution, but unfortunately it's not tail recursive. So it will consume some (linear) amount of stack space, and might even crash for a very long list.
Here's one based on the same idea, using the standard FP accumulator trick to get tail recursive behavior (as noted by Thomas):
let flatten2 ll =
let rec go acc = function
| [] -> List.rev acc
| l :: r -> go (List.rev_append l acc) r
in
go [] ll
As is often the case, the tail recursive version accumulates the result in reverse order, and reverses it at the end.
You can start by writing directly your algorithm, by decomposing the base cases of your input value, ie. the input list is either empty, or the head of the input list is empty, or the head of the input list has a head and a tail:
let rec flatten = function
| [] -> []
| [] :: t -> flatten t
| (x::y) :: t -> x :: (flatten (y::t))
You can then optimize the function, because this code is not tail-recursive and thus will crash when lists become too big. So you can rewrite this by using the usual technique:
let flatten list =
let rec aux accu = function
| [] -> accu
| [] :: t -> aux accu t
| (x::y) :: t -> aux (x::accu) (y::t) in
List.rev (aux [] list)
So my advice is: start by decomposing your problem based on the input types, and then later use accumulators to optimize your code.
I like this one, where the auxiliary function takes the accumulator, the first element of the list of lists, and the rest of the list of lists, it is clearer for me :
let flatten list =
let rec aux acc list1 list2 =
match list1 with
| x :: tail -> aux (x :: acc) tail list2
| [] ->
match list2 with
| [] -> List.rev acc
| x :: tail -> aux acc x tail
in
aux [] [] list
Thanks for all your help
Here is the code I used to solve this problem
let flatten list =
let rec flatten_each acc x =
match x with
[] -> acc
| head :: remainder -> head :: ( flatten_each acc remainder )
in
List.fold_right flatten_each ( List.rev list ) []
;;
Edit: as pointed out by Thomas this solution is not tail recursive. Tail recursive version is below
let flatten list =
let rec flatten_each acc x =
match x with
[] -> acc
| head :: remainder -> (flatten_each (acc # [head]) remainder )
in
List.fold_right flatten_each list []
;;