I'm writing a list reversal program for haskell.
I've got the idea for the list reversal and that has lead to the following code:
myreverse list1
| list1 == [] = list1
| otherwise = (myreverse(tail list1)):(head list1)
Unfortunately the above code results in the following error:
Occurs check: cannot construct the infinite type: a = [[a]]
Expected type: [[a]]
Inferred type: a
In the second argument of '(:)', namely '(head list1)'
In the expression: (myreverse(tail list1)):(head list1)
PS: I get the same sort of error when I run it on a snippet that I wrote called mylast coded below:
mylast list
| list == [] = []
| otherwise = mylast_helper(head list1)(tail list1)
mylast_helper item list2
| list2 == [] = item
| otherwise = mylast_helper(head list2)(tail list2)
Error occurs at the otherwise case of the recursive helper.
EDIT: Thanks for all the input, I guess I forgot to mention that the constraints of the question forbid the use of the ++ operator. I'll keep that in mind for future questions I create.
Cheers,
-Zigu
You are using the function
(:) :: a -> [a] -> [a]
with ill-typed arguments:
myReverse (tail list1) :: [a]
head list1 :: a
In your function, the list list1 must have type a. Hence the second argument, head list1, must have type [a]. GHC is warning you that it cannot construct the type you have specified for it. The head of a list is structurally smaller than the tail of a list, but you are telling it that the head of a list has type [a], yet the tail of a list has type a.
If you stare closely at your types, however, you will notice that you can append the head of list1 to the recursive call to myreverse using (++):
myReverse xs = case (null xs) of
True -> xs
False -> myReverse (tail xs) ++ [head xs]
Here,
[head xs] :: [a]
myReverse (tail xs) :: [a]
which aligns with the type of append:
(++) :: [a] -> [a] -> [a]
There are much better ways to implement reverse, however. The Prelude defines reverse as a left fold (. Another version of reverse can be implemented using a right fold, and is very similar to your myReverse function:
reverse xs = foldr (\x xs -> xs ++ [x]) [] xs
First off, try adding a signature to each of your functions; this will help the compiler know what you're trying to do and give you better error messages earlier on. A signature would look like this, for example: mylast :: [a] -> a. Then, instead of using guards (|), define your function through a series of equations, using pattern matching:
mylast :: [a] -> a
mylast (x:[]) = x
mylast (_:t) = mylast t
In GHCi, you can look at the type of something using :t term. That's the best general advice I can give... look carefully at the types and make sure they make sense for how you're using them.
The type of cons (:) is a -> [a] -> [a] - in other words, you give it an element and then a list and it puts the element at the start of the list. In your last line, you're doing the reverse - list first and then an element. To fix it up, change the : to the list concat operator ++:
myreverse list1
| list1 == [] = list1
| otherwise = (myreverse (tail list1)) ++ [head list1]
(To try and translate the error, it's saying "OK, the first argument to : you've given me is a list, therefore the second argument needs to be a list of elements of that same type, so a list of lists...BUT...you've given me an argument which is the type of an element of the list, so I need some type that is the same as a list of lists of that type, which I can't do. Bang!")
Ended up working on this question more and answering it myself.
Thanks a lot for the feedback. It pushed me along the right direction.
myreverse list1
| list1 == [] = list1
| otherwise = myreverse_h(list1)([])
myreverse_h list1 list2
| list1 == [] = list2
| otherwise = myreverse_h(tail list1)((head list1):list2)
Any comments on better code though? I don't think its as efficient as it could be...
Related
I'm trying to make a function which returns a list of the first element of each sub-list, including empty lists being returned as [].
let firstCol (lst: 'a list list) =
List.map List.head lst
This works as long as there are no empty lists, but I get the following error message when my input includes an empty list:
System.ArgumentException: The input list was empty.
How do I go about this? Thanks in advance.
You can use List.tryHead or write your own function from the ground, or with helpers like List.fold/List.foldBack.
If you do List.tryHead you get an option as a result, either Some element, or None if the list is empty. So you must think what happens in the None case. You cannot return an empty list for a sub-list, because a list must have the same type. But you could for example skip empty lists. Or just keep the Option. As it indicates when a list was empty.
let xs = [[1;2;3];[];[4;5;6];[];[7;8;9]]
printfn "%A" (List.map List.tryHead xs)
returning
[Some 1; None; Some 4; None; Some 7]
You could skip the empty sub-lists
printfn "%A" (List.choose List.tryHead xs)
so you get
[1;4;7]
or do it on your own, with List.foldBack
let firstCol xs =
let folder xs acc =
match List.tryHead xs with
| Some x -> x :: acc
| None -> acc
List.foldBack folder xs []
Or even more basic
let rec firstCol xs =
match xs with
| [] -> []
| []::xss -> firstCol xss
| (x::xs)::xss -> x :: firstCol (xss)
The last version is not tail-recursive, but anyway, you should try and train to understand such a recursive definition. And be able to turn such a function into an tail-recursive on your own.
What you're asking for can't be done with the signature you currently have. Consider this input:
[
[1; 2]
[]
[3; 4]
]
It looks like you're asking for the following output:
[
1
[]
3
]
However, that isn't a legal list in F# because its elements don't have the same type.
I think your best bet is just to use tryHead instead, as suggested in the other answers.
I need to define the function in Haskell's
which for a given list of lists will create a list of its last elements.
For example for [[1,2],[3,4]] it should return [2,4]
I tried to use pattern matching but ite returns only the last list :
lastElement :: [[a]] -> [a]
lastElement [] = error "error"
lastElement [x] = x
lastElement (x:xs) = lastElement xs
it gives me [3,4]
Problem
You are on the right track, the problem is that your code is not recursing. A recursive function on lists is usually of the form
f :: [a] -> [b]
f [] = y
f (x:xs) = y : f xs
After y is evaluated, that result is ":ed" to the recursive call. Now try to make your code so something similar. Also note that you don't need the lastElement [x] case, it's just plain reduntant for the recursion. However, this only applies some function to every element. You will also need a function f :: [a] -> a to get that last element from one single list. Your function as of now does just that, but there is a standard library function for that. Have a look at Hoogle: you can search library functions by type or description
Better Alternative
In this case, I would use a list comprehension as I think it would be more clear to read. Have a look at that as well
Best Alternative
Haskell being a functional language, it allows you to think more about what change to need to apply to your data, rather than what steps do you need to achieve. If you know them, you can use higher order function for this. In particular, the function map :: (a -> b) -> [a] -> [b]. As you can guess from this type definition, map takes a function, and applies it to every element of a list. It looks like you already know the last function, so you can use that:
lastElements :: [[a]] -> [a]
lastElements = map last
Look how neat and simple this code is now; no need to think about what the recursion does, you just see that it takes the last element from each list.
I will assume that you have beginner skills in Haskell and try to explain better what you are doing wrong.
lastElement :: [[a]] -> [a]
lastElement [] = error "error"
lastElement [x] = x
lastElement (x:xs) = lastElement xs
In this function, you are receiving a list of elements and returning the last of it. Occurs that those elements are lists too. In that way, applying lastElement [[1,2],[3,4]] will give to you his last element how is the list [3,4]. Since you need to enter a list [x,y,z] in which x y and z are lists and you wanna return [last of x, last of y, last of z], we need two things:
1. A function which receives a list of Int and return his last element
2. Apply this function to a (list of (lists of a)) [[a]]
To make (1) we can easily modify your function lastElement just like this:
lastElement :: [a] -> a
lastElement [] = error "error"
lastElement [x] = x
lastElement (x:xs) = lastElement xs
Now, lastElement receives one list and return its last element.
To make (2) we just need to create a mapping function like this:
mapping :: ([a] -> a) -> [[a]] -> [a]
mapping _ [] = []
mapping f (x:xs) = (f x) : (mapping f xs)
In that way, you can call mapping lastElement [[1,2],[3,4]] that will give you [2,4].
I need to say that none of this is needed if you knew two functions which is last who do the same as (1) and map who do the same as (2). Knowing this, you can do like Lorenzo already done above:
lastElements :: [[a]] -> [a]
lastElements = map last
I have been working with Haskell for a little over a week now so I am practicing some functions that might be useful for something. I want to compare two lists recursively. When the first list appears in the second list, I simply want to return the index at where the list starts to match. The index would begin at 0. Here is an example of what I want to execute for clarification:
subList [1,2,3] [4,4,1,2,3,5,6]
the result should be 2
I have attempted to code it:
subList :: [a] -> [a] -> a
subList [] = []
subList (x:xs) = x + 1 (subList xs)
subList xs = [ y:zs | (y,ys) <- select xs, zs <- subList ys]
where select [] = []
select (x:xs) = x
I am receiving an "error on input" and I cannot figure out why my syntax is not working. Any suggestions?
Let's first look at the function signature. You want to take in two lists whose contents can be compared for equality and return an index like so
subList :: Eq a => [a] -> [a] -> Int
So now we go through pattern matching on the arguments. First off, when the second list is empty then there is nothing we can do, so we'll return -1 as an error condition
subList _ [] = -1
Then we look at the recursive step
subList as xxs#(x:xs)
| all (uncurry (==)) $ zip as xxs = 0
| otherwise = 1 + subList as xs
You should be familiar with the guard syntax I've used, although you may not be familiar with the # syntax. Essentially it means that xxs is just a sub-in for if we had used (x:xs).
You may not be familiar with all, uncurry, and possibly zip so let me elaborate on those more. zip has the function signature zip :: [a] -> [b] -> [(a,b)], so it takes two lists and pairs up their elements (and if one list is longer than the other, it just chops off the excess). uncurry is weird so lets just look at (uncurry (==)), its signature is (uncurry (==)) :: Eq a => (a, a) -> Bool, it essentially checks if both the first and second element in the pair are equal. Finally, all will walk over the list and see if the first and second of each pair is equal and return true if that is the case.
I had an interview question, and it has been bugging me since then.
I have a function, fill, that does the computation like taking two lists and then replacing 2s in the second list, where ever there are 2s in the first list and also once 2s are filled in the second list from the first list, then it can flow till a 1 is encountered. For eg:
Two lists [2,1,2,1,2] [0,0,1,0,0] is passed, so the output I get is [2,2,1,2,2]. Now, I want to write a function that takes an argument something like this: [[2,1,2,1,2],[0,0,1,0,0],[0,0,0,0,0]], I want to apply my above function recursively till the end of this list of lists. So like first [2,1,2,1,2] [0,0,1,0,0] are passed to fill, then it should get the result [2,2,1,2,2], then [2,2,1,2,2] and [0,0,0,0,0] should be passed, getting the result [2,2,2,2,2]. How can I do that?
EDIT:
I did this:
fillAll::[[Int]]->[Int]
fillAll [] = []
fillAll (x:xs) =
(foldl' seep x xs) $
helper2 x
helper2:: [Int] -> Bool
helper2 lst =
if 2 `elem` lst then True else False
So, you have your function fill:
fill :: [Int] -> [Int] -> [Int]
And you want to turn this into a function which takes a list of lists:
fillRec :: [[Int]] -> [Int]
This is a natural case for a fold. This repeatedly 'folds' each element of a list together using a combining function. We need to make sure the list isn't empty:
fillRec [] = []
fillRec (x : xs) = foldl fill x xs
This version of foldl (e.g. folds from the left, rather than from the right) is non-strict, which can cause large memory accumulation. It's better to use the strict variant foldl' from Data.List:
fillRec (x : xs) = foldl' fill x xs
I'm going to assume that you already have fill :: [Int] -> [Int] -> [Int] defined. If so, this problem is pretty easy to solve using a fold. Explicitly, you could do something like
fillAll :: [[Int]] -> [Int]
fillAll [] = []
fillAll (x:xs) = go x xs
where
go first [] = first
go first (second:rest) = go (fill first second) rest
Or you can use one of the built-in folds:
fillAll [] = []
fillAll (x:xs) = foldl fill x xs
but as Impredicative points out, you'll have better performance with foldl' from Data.List
I'm trying to write my implementation of remdps, function, which removes nearest duplicates in a list. For example: "aaabbbsscaa" should became "absca". I have to use foldl. Here is my attempt:
helper :: Eq a => [a] -> a -> [a]
helper [] ele = [ele]
helper newlist ele = if tail newlist /= ele then newlist:ele
else newlist
remdps :: Eq a => [a] -> [a]
remdps list = foldl helper [] list
main = putStrLn (show (remdps "aabssscdddeaffff"))
And the error:
4.hs:4:41:
Could not deduce (a ~ [a])
from the context (Eq a)
bound by the type signature for helper :: Eq a => [a] -> a -> [a]
at 4.hs:2:11-33
`a' is a rigid type variable bound by
the type signature for helper :: Eq a => [a] -> a -> [a]
at 4.hs:2:11
In the second argument of `(/=)', namely `ele'
In the expression: tail newlist /= ele
In the expression:
if tail newlist /= ele then newlist : ele else newlist
4.hs:4:50:
Could not deduce (a ~ [a])
from the context (Eq a)
bound by the type signature for helper :: Eq a => [a] -> a -> [a]
at 4.hs:2:11-33
`a' is a rigid type variable bound by
the type signature for helper :: Eq a => [a] -> a -> [a]
at 4.hs:2:11
In the first argument of `(:)', namely `newlist'
In the expression: newlist : ele
In the expression:
if tail newlist /= ele then newlist : ele else newlist
4.hs:4:58:
Could not deduce (a ~ [a])
from the context (Eq a)
bound by the type signature for helper :: Eq a => [a] -> a -> [a]
at 4.hs:2:11-33
`a' is a rigid type variable bound by
the type signature for helper :: Eq a => [a] -> a -> [a]
at 4.hs:2:11
In the second argument of `(:)', namely `ele'
In the expression: newlist : ele
In the expression:
if tail newlist /= ele then newlist : ele else newlist
fish: Unknown command './4'
ghc 4.hs; and ./4
The question is always the same:). What's wrong?
//edit
OK, I have a working code. It uses reverse and ++, so it's very ugly:).
helper :: Eq a => [a] -> a -> [a]
helper [] ele = [ele]
helper newlist ele = if head (reverse newlist) /= ele then newlist ++ [ele]
else newlist
remdps :: Eq a => [a] -> [a]
remdps list = foldl helper [] list
main = putStrLn (show (remdps "aabssscdddeaffff"))
What you're probably trying to do is this:
helper :: Eq a => [a] -> a -> [a]
helper [] ele = [ele]
helper newlist ele = if last newlist /= ele then newlist ++ [ele]
else newlist
The changes:
: works only in one way: on the left is the head of the list (type a), on the right the tail (type [a]). It's sometimes also called "cons". What you want to do is called "snoc": on its right is the last element of the list (type a), and on the left the initial part (type [a]).
"snoc" doesn't exist in the Prelude, so instead, you just write it in a different way: newlist ++ [ele]. (Compare this to x : xs == [x] ++ xs.)
tail newlist == ele becomes last newlist == ele. tail gets the list without its head, but you want to compare the last element of newlist. For that purpose, you have last. (By the way, to get the initial part of a list, you can use init.)
Note that you've also swapped the branches of your if-statement, leaving you with aaa as the answer. -edit- I see that you've updated that now ;)
Also note that this is a very slow approach. Every "snoc" and last will take longer as the answer of remdps grows, because Prelude lists are much better at "cons" and head. Try rewriting the function so that it uses "cons" instead. Hint: you'll need reverse at some point.
Furthermore, this function will not work when used with infinite lists, because of the way foldl works. It might be an interesting exercise to rewrite this function to use foldr instead.
The type annotation of helper suggest that ele is of type a
And you do the following test (tail(newlist) == ele), but tail if of type [a]
You cannot compare two value if different type.
This is not the only error.
I suggest you take a look at the docs for Data.List. Specifically for tail you'll see that the type is [a] -> [a], so obviously it doesn't return the last element of the list as one might think.
If you're looking to get a single element of out of a list (the last one) you need something with type [a] -> a. The power of haskell comes from the fact that this information is almost enough to find the right function.
Just Hoogle it!
P.S. As a side note - this approach is quite slow, as mentioned in Tinctorius' answer
To expand on my second comment, though this doesn't answer your question as posed, I would very much not use foldl to do this. Back in my Scheme days I'd solve it with this pet kfoldr function of mine, which I've translated to Haskell here:
-- | A special fold that gives you both left and right context at each right
-- fold step. See the example below.
kfoldr :: (l -> a -> l) -> l -> (l -> a -> r -> r) -> (l -> r) -> [a] -> r
kfoldr advance left combine seedRight [] = seedRight left
kfoldr advance left combine seedRight (x:xs) = combine left x (subfold xs)
where subfold = let newLeft = advance left x
in newLeft `seq` kfoldr advance newLeft combine seedRight
removeDuplicates :: Eq a => [a] -> [a]
removeDuplicates = kfoldr advance Nothing step (const [])
where
-- advance is the left context generator, which in this case just
-- produces the previous element at each position.
advance _ x = Just x
-- step's three arguments in this case are:
-- (a) the element to the left of current
-- (b) the current element
-- (c) the solution for the rest of the list
step Nothing x xs = x:xs
step (Just x') x xs
| x == x' = xs
| otherwise = x:xs
Haskell's Data.List library has mapAccumL and mapAccumR which are similar but they map instead of folding. There's also the intimately related scanl and scanr, which can probably be used to implement kfoldr (but I haven't bothered to try).