I've tried to use a function that calculate the reverse of a list. So I can use it in other function that will be the palindrome function, but always I get an error.
The first one works.
This is the code:
rev :: [a] -> [a]
rev [] = []
rev (x:xs) = rev xs ++ [x]
palindrome :: [a] -> Bool
palindrome [] = True
palindrome (x:xs) = if xs == rev (x:xs) then True else False
I have to mention that I have to do it with that signature: [a] -> Bool
Someday I will muster the energy to put together a megaquestion to address two common beginner list mistakes: thinking that [x] matches a list of any length, and thinking that any function on lists must have [] and x:xs patterns. This question is an example of the latter. When you do the same thing regardless of list length, you don't need multiple patterns! Just palindrome xs = ... is fine. Try writing your palindrome function again with this in mind; your bug will be fixed as a side effect.
Related
So, I know, there is a built in function to reverse a list in Haskell, but I'm trying to write my own little function, just to practice some Haskell. I thought of the following code, which sadly is not working. Could you guys tell me what I did wrong?
rev :: [Int] -> [Int]
rev [] = []
rev [x] = last [x] : rev init [x]
If you want to do it efficiently, I'd recommend you use an accumulator:
rev :: [a] -> [a]
rev xs = go xs []
where
go :: [a] -> [a] -> [a]
go [] ys = ys
go (x:xs) ys = go xs (x:ys)
The function go, at each step, removes one element from the first list xs and prepends it to the second list ys. This is similar to popping from a stack and pushing to another stack -- which reverses the order.
Since we only use a constant amount of time at each recursive call, we get O(n) complexity, where n is the list length.
Instead, if at each recursive call we use last or append with ... ++ [x], we pay O(n) for each call, hence O(n^2) overall.
You almost had it.
rev :: [Int] -> [Int]
rev [] = []
rev x = last x : rev (init x)
Explanation: [x] was a list containing x, whereas you want to operate directly with x
ps. here's the documentation for Data.List. And remember to import Data.List
Well, you could do something like this:
rev :: [Int] -> [Int]
rev [] = []
rev (x:l) = (rev l) ++ [x]
The 3rd line takes the first element from the list and then creates a list containing only that element. This is appended to the result of the recursion rev l call.
I am new to haskell and I was attempting a few coding problems that I previously completed for java, however the following problem has me stumped.
Basically the idea is to write a function that takes in a list of integers ([Int]) establishes whether a list of integers has consecutive 1's within it. For example the output of the following would be:
Input: func [0,0,1,1,0]
Output: True
A sample solution for this problem in haskell would be greatly appreciated,
Thanks
One way would be to use pattern matching to look for consecutive ones at the head of the list, and advance down the list until you find them, or you run out of elements to look at.
consecutiveOnes [] = False
consecutiveOnes (1:1:_) = True
consecutiveOnes (_:xs) = consecutiveOnes xs
This is a solution:
consecutiveOnes :: [Int] -> Bool
consecutiveOnes xs = auxOnes False xs
auxOnes :: Bool -> [Int] -> Bool
auxOnes b [] = False
auxOnes b (x:xs) = case (x==1 && b) of {
True -> True;
False -> auxOnes (x==1) xs;
};
Another way would be using the isInfixOf method and asking if [1,1] appears anywhere on your list:
consecutiveOnes :: [Int] -> Bool
consecutiveOnes xs = isInfixOf [1,1] xs
The isInfixOf function takes two lists and returns True iff the first
list is contained, wholly and intact, anywhere within the second.
But I'm sure there are many other ways of doing it.
You could also do it this way:
consecutiveOnes [] = False
consecutiveOnes xs = any (== (1,1)) $ zip xs (tail xs)
If
xs == [0,1,1,2,3,4]
Then
tail xs == [1,1,2,3,4]
Zipping them together you get a list of pairs, where each pair is an element of the list and the element after it.
zip xs (tail xs) == [(0,1),(1,1),(1,2),(2,3),(3,4)]
I have a function which was written in list comprehension. As a learning I decided to try to convert this function into a functional application using map, zip, fold, etc. I am having a really hard time converting this particular one.
It might seem unreasonable for what it is doing, but it is part of a bigger function and I want to get this piece working first.
combination :: Int -> [a] -> [([a],[a])]
combination 0 xs = [([],xs)]
combination n (x:xs) = [ (x:ys,zs) | (ys,zs) <- combination (n-1) xs ]
It's just a map:
combination :: Int -> [a] -> [([a],[a])]
combination 0 xs = [([],xs)]
combination n (x:xs) = map (\(ys, zs) -> (x:ys,zs)) (combination (n-1) xs)
The language I'm using is a subset of Haskell called Core Haskell which does not allow the use of the built-in functions of Haskell. For example, if I were to create a function which counts the number of times that the item x appears in the list xs, then I would write:
count = \x ->
\xs -> if null xs
then 0
else if x == head xs
then 1 + count x(tail xs)
else count x(tail xs)
I'm trying to create a function which outputs a list xs with its duplicate values removed. E.g. remdups (7:7:7:4:5:7:4:4:[]) => (7:4:5:[])
can anyone offer any advice?
Thanks!
I'm guessing that you're a student, and this is a homework problem, so I'll give you part of the answer and let you finish it. In order to write remdups, it would be useful to have a function that tells us if a list contains an element. We can do that using recursion. When using recursion, start by asking yourself what the "base case", or simplest possible case is. Well, when the list is empty, then obviously the answer is False (no matter what the character is). So now, what if the list isn't empty? We can check if the first character in the list is a match. If it is, then we know that the answer is True. Otherwise, we need to check the rest of the list -- which we do by calling the function again.
elem _ [] = False
elem x (y:ys) = if x==y
then True
else elem x ys
The underscore (_) simply means "I'm not going to use this variable, so I won't even bother to give it a name." That can be written more succinctly as:
elem _ [] = False
elem x (y:ys) = x==y || elem x ys
Writing remdups is a little tricky, but I suspect your teacher gave you some hints. One way to approach it is to imagine we're partway through processing the list. We have part of the list that hasn't been processed yet, and part of the list that has been processed (and doesn't contain any duplicates). Suppose we had a function called remdupHelper, which takes those two arguments, called remaining and finished. It would look at the first character in remaining, and return a different result depending on whether or not that character is in finished. (That result could call remdupHelper recursively). Can you write remdupHelper?
remdupHelper = ???
Once you have remdupHelper, you're ready to write remdups. It just invokes remdupHelper in the initial condition, where none of the list has been processed yet:
remdups l = remdupHelper l [] -- '
This works with Ints:
removeDuplicates :: [Int] -> [Int]
removeDuplicates = foldr insertIfNotMember []
where
insertIfNotMember item list = if (notMember item list)
then item : list
else list
notMember :: Int -> [Int] -> Bool
notMember item [] = True
notMember item (x:xs)
| item == x = False
| otherwise = notMember item xs
How it works should be obvious. The only "tricky" part is that the type of foldr is:
(a -> b -> b) -> b -> [a] -> b
but in this case b unifies with [a], so it becomes:
(a -> [a] -> [a]) -> [a] -> [a] -> [a]
and therefore, you can pass the function insertIfNotMember, which is of type:
Int -> [Int] -> [Int] -- a unifies with Int
I've just started to learn Haskell and I am trying to write a simple function that takes a list of strings and reverses each string in the list:
revComp :: [String] -> [String]
revComp [] = []
revComp [x] = [] ++ [reverse x]
revComp (x:xs) = revComp [xs]
When I try to load my code in GHCI, I get an error:
Couldn't match expected type `Char' with actual type `[Char]'
Expected type: String
Actual type: [String]
Could anyone explain what and where my problem is? Thanks very much.
The first three lines are fine. Your type signature is correct, the second line is correct, and so is the third. (However, [] ++ [reverse x] is the same as [reverse x].)
The fourth line, however, is wrong. Not only do you not use x at all on the right-hand side, but you have a type error: revComp [xs] calls revComp with a single-element list that has xs as its only element. Here, x is the first element of the list, and xs is the rest of the list. So, since xs has the type [String], [xs] has the type [[String]], but revComp takes a [String]! You want to reverse x, and prepend that to the result of reversing the rest of the list.
You can use revComp xs to reverse each string in the rest of the list, and (:) to prepend a value to a list (with the same syntax seen in the x:xs pattern you used on the left-hand side). That should be enough information for you to fix the last line. This makes the third line redundant, by the way, since [x] is just x:[].
ehird's answer is really complete, but I wanted to point out -- as a reference -- the "good/shorter" way to implement that function in real code, since you're new.
It can be defined as the partial application of map to reverse:
Prelude> let revComp = map reverse
Prelude> revComp ["olleh", "dlrow"]
["hello","world"]
It results in a function revComp :: [[a]] -> [[a]] (and not [String] -> [String] since both map and reverse work on any type of lists) that maps reverse to every element of the input list, returning the list of results.
The third line might not be required even with your example. The edge case (terminating condition) can be only the empty list. You can skip the condition for the single element.
revComp :: [String] -> [String]
revComp [] = []
revComp (x:xs) = reverse x : revComp xs
Don't know if there is a CS term for this. Someone in the community can add that information.
A few more ways to do the same thing:
revstr [] = []
revstr (x:xs) = reverse x : revstr xs
revstr2 [] = []
revstr2 (x:xs) = [reverse x] ++ revstr2 xs
revstr3 xs = map reverse xs
revstr4 = map reverse -- map takes 2 arguments ;)
revstr5 xs = foldl step [] xs
where step acc x = acc ++ [reverse x]
revstr6 xs = foldr step [] xs
where step x acc = reverse x : acc