Beginner Type Errors using Filter - haskell

I'm just starting to use Haskell, and I'm having what most of you reading would probably consider a beginner blunder.
Consider a list of tuples myTupleList = [(3,6),(4,8),(1,3)]
Nice. I wrote this function to return the list of tuples in which the second element in the first tuple, is double the first element:
(Ex using myTupleList: double myTupleList , which returns [(3,6),(4,8)] )
double [] = []
double (x:xs)
|(snd x) == 2 * (fst x) = x: double xs
|otherwise = double xs
Now I'm sure this isn't the prettiest function in the world, but it works. The problem now is adapting it to use filter. This is my current attempt:
double [] = []
double xs = filter ((2 * (fst(head xs))) == (snd(head xs))) xs
To my undestanding, filter recieves two arguments: a boolean expression and a list. However, I'm getting the following error:
Couldn't match expected type ‘(a, a) -> Bool’
with actual type ‘Bool’
• Possible cause: ‘(==)’ is applied to too many arguments
In the first argument of ‘filter’, namely
‘((2 * (fst (head xs))) == (snd (head xs)))’
In the expression:
filter ((2 * (fst (head xs))) == (snd (head xs))) xs
In an equation for ‘double’:
double xs = filter ((2 * (fst (head xs))) == (snd (head xs))) xs
• Relevant bindings include
xs :: [(a, a)] (bound at Line 9, Column 8)
double :: [(a, a)] -> [(a, a)] (bound at Line 8, Column 1)
I'm sure this is just some silly error or limitation of Haskell as a functional language that I'm not accustomed to or understanding properly, but it would be great to get some help with this.
Thanks

filter expects a function a -> Bool, but (2 * (fst(head xs))) == (snd(head xs)) is not a function that maps an element to a Bool, but simply a Bool. It does not make much sense here to use head x, you use the parameter to get "access" to the element:
double :: (Eq a, Num a) => [(a, a)] -> [(a, a)]
double xs = filter (\x -> 2 * fst x == snd x) xs
You can use pattern matching to unpack the 2-tuple and thus no longer need fst and snd. Furthermore you can perform an η-reduction, and thus remove xs both in the head and the body of double in this case:
double :: (Eq a, Num a) => [(a, a)] -> [(a, a)]
double = filter (\(a, b) -> 2 * a == b)
This gives us:
Prelude> double [(3,6),(4,8),(1,3)]
[(3,6),(4,8)]
We can even make the predicate point-free:
double :: (Eq a, Num a) => [(a, a)] -> [(a, a)]
double = filter (uncurry ((==) . (2 *)))

Related

Rewrite using higher order functions

This code displays a list of the second elements of every tuple in xs based on the first element of the tuple (x).
For my assignment, I should define this in terms of higher order functions map and/or filter.
I came up with
j xs x = map snd . filter (\(a,_) -> a == x). xs
You can solve this by using parthesis and remove the last dot (.) before the xs:
j :: Eq a => [(a, b)] -> a -> [b]
j xs x = (map snd . filter ((a,_) -> a == x)) xs
here we thus construct a function between the parenthesis, and we use xs as argument. If you use f . x, then because of (.) :: (b -> c) -> (a -> b) -> a -> c, it expects x to be a function and it constructs a new function, but in your case xs is an argument, not another function to a use in the "chain".
The (a, _) -> a == x, can be replaced by (x ==) . fst:
j :: Eq a => [(a, b)] -> a -> [b]
j xs x = (map snd . filter ((x ==) . fst)) xs

Couldn't match expected type `Int' with actual type `a'

import Data.List
data Tree a = Leaf a | Node (Tree a) a (Tree a) deriving Show
toTree :: Ord a => [a] -> Tree a
toTree xs = Node (balancedTree (take n xs')) (xs'!!n) (balancedTree (drop n xs'))
where
xs' = sort xs
n = middle xs
middle :: Num a => [a] -> a
middle xs = fromIntegral ((length xs `div` 2) + 1)
balancedTree :: Ord a => [a] -> Tree a
balancedTree (x:[]) = Leaf x
balancedTree xs = Node (balancedTree (take n xs')) (xs'!!n) (balancedTree (drop n xs'))
where
xs' = sort xs
n = middle xs
This is my code for converting from a list to a binary tree. I know there are many mistakes but I just want to get the types errors sorted before I start debugging. I get the following errors in both the "toTree" method and the "balancedTree" method as they are both really the same and will be condensed into one when the errors are sorted out.
ex7.hs:6:38: error:
* Couldn't match expected type `Int' with actual type `a'
`a' is a rigid type variable bound by
the type signature for:
toTree :: forall a. Ord a => [a] -> Tree a
at ex7.hs:5:1-32
* In the first argument of `take', namely `n'
In the first argument of `balancedTree', namely `(take n xs')'
In the first argument of `Node', namely
`(balancedTree (take n xs'))'
* Relevant bindings include
xs' :: [a] (bound at ex7.hs:8:9)
n :: a (bound at ex7.hs:9:9)
xs :: [a] (bound at ex7.hs:6:8)
toTree :: [a] -> Tree a (bound at ex7.hs:6:1)
|
6 | toTree xs = Node (balancedTree (take n xs')) (xs'!!n) (balancedTree (drop n xs'))
| ^
I have tried for hours to fix it by searching stackOverflow but I can't figure it out. The type declaration of "toTree" must stay the same. Also the definition of Tree should stay the same.
My understanding is that "take" required an "Int" and I am giving it an "a". I do not know how I can fix this.
The problem is that middle returns an a, not an Int. Indeed:
middle :: Num a => [a] -> a
middle xs = fromIntegral ((length xs `div` 2) + 1)
But in your balancedTree, you use it as if it is an index, and take n, drop n, and !! n require n to be an Int, indeed:
balancedTree :: Ord a => [a] -> Tree a
balancedTree (x:[]) = Leaf x
balancedTree xs = Node (balancedTree (take n xs')) (xs'!!n) (balancedTree (drop n xs'))
where
xs' = sort xs
n = middle xs
The type signature does not make much sense either. You can calculate the length over any list, not only from lists that consist out of numbers. You thus should construct a function that returns the index in the middle of the list and use that. For example:
middle :: [a] -> Int
middle = (length xs `div` 2) + 1
That being said, using length, etc. is usually not a good idea in Haskell. length requires O(n) time, and furthermore for infinite lists, it will get stuck in an infinite loop. Often if you use functions like length, there is a more elegant solution.
Instead of using a "top-down" approach, it might be better to look at a "bottom-up" approach, where you iterate over the items, and on the fly construct Leafs, and group these together in Nodes until you reach the top.

Guards and where haskell

I have a very basic Haskell function.
It should prepend a tuple to list if not present returning it.
Added tuple needs to be edited before prepending.
I expect a function whose type is this:
Num t => (a, t) -> [(a, t)] -> [(a, t)]
Function is this:
update x lst
| hasElement x lst == True = addElement x lst
| otherwise = lst
where hasElement element list = not (null (filter ((==element).fst) list))
addElement a b = (fst a, (snd a) +1) : b
but I got an error when I try to load the module:
• Occurs check: cannot construct the infinite type: a ~ (a, t)
Expected type: [(a, t)]
Actual type: [((a, t), t)]
• In the second argument of ‘addElement’, namely ‘lst’
In the expression: addElement x lst
In an equation for ‘update’:
update x lst
| hasElement x lst == True = addElement x lst
| otherwise = lst
where
hasElement element list
= not (null (filter ((== element) . fst) list))
addElement a b = (fst a, (snd a) + 1) : b
• Relevant bindings include
lst :: [((a, t), t)] (bound at pip.hs:40:10)
x :: (a, t) (bound at pip.hs:40:8)
update :: (a, t) -> [((a, t), t)] -> [(a, t)]
(bound at pip.hs:40:1)
The addElement return type seems breaks all up since commenting it out makes the module work.
Question is: what's wrong?
Trying function alone seems working as I expect.
Thanks,
FB
The reason for that particular error is that element contains both a key and a value, but by (==element) . fst you try to compare only the key.
The best way to actually get only at the key is to pattern match it right in the function argument. Note that you don't really need the element variable at all, nor the other arguments to the local functions:
update (key,y) lst
| hasElement = addElement -- comparing `==True` is a no-op!
| otherwise = lst
where hasElement = not . null $ filter ((==key).fst) lst
addElement = (key, y+1) : b
I'd question though if this behaviour of addElement is really what you want: you're not updating the existing element with a given key, but adding a new element with the same key?
Also, the combination of not, null and filter is needlessly complicated. You can just use
hasElement = any ((==key).fst) lst
Finally, the signature Num a => ... is actually not strong enough: you're comparing keys with ==. That only works if the keys have an Eq instance. So, this is the correct signature:
(Eq a, Num t) => (a, t) -> [(a, t)] -> [(a, t)]

How to pattern match the end of a list?

Say I wanted to remove all zeros at the end of a list:
removeEndingZeros :: (Num a, Eq a) => [a] -> [a]
removeEndingZeros (xs ++ [0]) = removeEndingZeros xs
removeEndingZeros xs = xs
This does not work because of the (++) operator in the argument. How can I determine the end of a list through pattern-matching?
There is a function in Data.List to do this:
dropWhileEnd :: (a -> Bool) -> [a] -> [a]
dropWhileEnd p = foldr (\x xs -> if p x && null xs then [] else x : xs) []
So you can drop the trailing zeros with
dropWhileEnd (== 0)
Another, very similar, function can be implemented like this:
dropWhileEnd2 :: (a -> Bool) -> [a] -> [a]
dropWhileEnd2 p = foldr (\x xs -> if null xs && p x then [] else x : xs) []
dropWhileEnd2 p has exactly the same semantics as reverse . dropWhile p . reverse, but can reasonably be expected to be faster by a constant factor. dropWhileEnd has different, non-comparable strictness properties than the others (it's stricter in some ways and less strict in others).
Can you figure out circumstances under which each can be expected to be faster?

Using few functions in Haskell together

I made this code where I need to find elements in a list that appears only once
for example: for input [1,2,2,3,4,4], the output will be: [1,3]
unique :: =[a]->[a]
unique xs =[x|x<-xs, elemNum x xs ==1]
elemNum :: Int -> [Int]->[Int]
elemNum x (y:ys)
| x==y =1+ elemNum x ys
| otherwise =elemNum x ys
However I am getting an error :
Not in scope: `unique'
Is this the correct way to use 2 function in Haskell? (define them at the same file), What'a wrong with the code?
There are a few problems in your code:
type signature of unique is wrong, it should be
unique :: (Eq a) => [a] -> [a]
that type constraint (Eq a) comes from elemNum
type signature of elemNum also wrong, it should be
elemNum :: (Eq a) => a -> [a] -> Int
that type constraint comes from ==, and the type of its first parameter no need to be Int, but its return type should be Int because you want to find out how many x in xs.
Also, you forgot to deal with empty list in that definition.
Here is a fixed version of your code:
unique :: (Eq a) => [a] -> [a]
unique xs =[x| x<-xs, elemNum x xs == 1]
elemNum :: (Eq a) => a -> [a] -> Int
elemNum x [] = 0
elemNum x (y:ys)
| x==y = 1 + elemNum x ys
| otherwise = elemNum x ys
Here is another implementation:
onlyOnce [] = []
onlyOnce (x:xs)
| x `elem` xs = onlyOnce $ filter (/=x) xs
| otherwise = x : onlyOnce xs
If x occurs in xs, then the result of onlyOnce (x:xs) should be the same as the result of applying onlyOnce to the result of removing all occurrences of x from xs; otherwise, x occurs in (x:xs) only once, so x should be part of the final result.
You have an equals sign in the Type declaration for unique:
unique :: =[a]->[a]
should be
unique :: [a] -> [a]
In my opinion it is much easier to implement this function using functions from Data.List module:
import Data.List
unique :: (Ord a) => [a] -> [a]
unique = map (\(y,_) -> y) . filter (\(x,l) -> l == 1) . map (\l#(x:xs) -> (x,length l)) . group . sort

Resources