Guards and where haskell - 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)]

Related

Haskell Expected type: [t0 a0] Actual type: [a]

data PossibleTuple a = Multiple (a, Int) | Single a
pack :: (Eq a) => [a] -> [a]
{-
...
-}
encode_modified' :: (Eq a) => [a] -> [PossibleTuple a]
encode_modified' [] = []
encode_modified' x = map (\x -> element x) (pack x)
where
element x
| length x > 1 = Multiple (x, length x)
| otherwise = Single x
I'm trying to do this:
encodeModified "aaaabccaadeeee"
[Multiple 4 'a',Single 'b',Multiple 2 'c',
Multiple 2 'a',Single 'd',Multiple 4 'e']
but I get this error:
* Couldn't match type `a' with `t0 a0'
`a' is a rigid type variable bound by
the type signature for:
encode_modified' :: forall a. Eq a => [a] -> [PossibleTuple a]
at src/Lib.hs:117:1-54
Expected type: [t0 a0]
Actual type: [a]
* In the second argument of `map', namely `(pack x)'
In the expression: map (\ x -> element x) (pack x)
In an equation for encode_modified':
encode_modified' x
= map (\ x -> element x) (pack x)
where
element x
| length x > 1 = Multiple (x, length x)
| otherwise = Single x
* Relevant bindings include
x :: [a] (bound at src/Lib.hs:119:18)
encode_modified' :: [a] -> [PossibleTuple a]
(bound at src/Lib.hs:118:1)
|
119 | encode_modified' x = map (\x -> element x) (pack x)
| ^^^^^^
Why would pack x need to have the type t0 a0? x is of type a0 and thus pack x would have type [a0].
All the types seem to match. The output of the map function is PossibleTuple a0. I don't even know where the a0 t0 comes from.
What type do you suppose element has? You call length on its argument, meaning you think it takes a list as input. However, you also map it over a list of type [a], meaning you think it can take any type a as input. This is a type mismatch.
Similarly you say you hope that your result will look like [Multiple (4, 'a')], but your element function can never produce this result. The first element in each tuple is the length of the second element, and length 'a' is a type error.
The first thing I would do is re-examine the type of pack, though. It can't do anything with its current type that seems very relevant. Probably it should be Eq a => [a] -> [[a]]. After that you will have more type errors to resolve, leading to a better definition of element.
Multiple 4 'a'
This does not match the value constructor you defined. This is the constructor you defined
data PossibleTuple a = Multiple (a, Int) | Single a
So to construct Multiple, you should do Multiple ('a', 4). Conversely, if you want to do Multiple 4 'a', then your constructor should read
data PossibleTuple a = Multiple Int a | Single a
It should be pack :: Eq a => [a] -> [[a]].
This function already exists, it is called group. It groups together consecutive elements of a list, which are equal to one another.
Then element needs just a small tweak to work,
where
element x
| length x > 1 = Multiple (.... x, length x)
| otherwise = Single (.... x)
with the same name appearing on both ....s. Normally using that function is frowned upon but here it will be correct by construction.
Or you could use # patterns in pattern matching, like
where
element x#(h:_)
...........
This encoding is known as run-length encoding, in case you were wondering.
To easier see what's going on, it usually helps mentally if we name the lists by variables in plural, like using xs for a list of xs (xs is to be read like it rhymes with "axes"):
encode_modified' :: (Eq a) => [a] -> [PossibleTuple a]
encode_modified' [] = []
encode_modified' x = -- map (\x -> element x) (pack x)
map (\xs -> element xs) (pack x)
where
element xs
-- | length x > 1 = Multiple (x, length x) -- length of "x"??
| length xs > 1 = Multiple ( x , length xs) -- no, of "xs"!!
---
| otherwise = Single x
-----
and the (underscored) plurality type mis-matches are now self-evident.

Recursive syntax in haskell using and

I am trying to create a recursive function that takes and input List of List that looks like this: [[1,2], [4], [3], [1]] and returns a Bool. It is supposed to check whether all lists include at least one unique number. I am trying to do this recursively using the two function below.
Function that removes all elements from the first list in the second list:
helper :: Eq a => [a] -> [a] -> [a]
helper a b = filter (`notElem` b) a
Main function:
function :: [[Int]] -> Bool
function [] = True
function (x:y:xs) = (not (null r)) and (function (r ++ xs))
where r = helper(x,y)
However, I get these two errors from the compiler:
Couldn't match expected type ‘(t0 Bool -> Bool) -> Bool -> Bool’
with actual type ‘Bool’
The function ‘not’ is applied to three arguments,
but its type ‘Bool -> Bool’ has only one
In the expression: (not (null r)) and (function (r ++ xs))
In an equation for ‘function’:
function (x : y : xs)
= (not (null r)) and (function (r ++ xs))
where
r = helper (x, y)
I am new to Haskell and not fully comfortable with the Haskell syntax.
First issue - calling a function with multiple arguments. This is done with the following syntax: myFunction a b (not myFunction (a, b)).
The reason for this is that (a, b) is a tuple. Here's a link with some info on tuples
Second issue - you are using and instead of &&
Third issue - you are trying to combine r and xs with ++ but the type of r is [Int] whereas the type of xs is [[Int]]. If your goal is to prepend r to xs then you can do this with :
helper :: Eq a => [a] -> [a] -> [a]
helper a b = filter (`notElem` b) a
function :: [[Int]] -> Bool
function [] = True
function (x:y:xs) = not (null r) && function (r : xs)
where r = helper x y

Beginner Type Errors using Filter

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 *)))

First element in a list haskell

So i need to do a find2 method that take the first Element out.
For example find2 :: (a -> Bool) -> [a] -> a
and find2 (>4) [1 .. 10]
Should have a the output 5
I am not good with haskell, but i want to learn it.
My first try was
find2 :: (a -> Bool) -> [a] -> a
find2 p [] = []
find2 p (x:xs)
|p x = x+1
|otherwise = finde p xs
but i am getting an error
* Couldn't match expected type `a' with actual type `[a0]'
`a' is a rigid type variable bound by
the type signature for:
find2 :: forall a. (a -> Bool) -> [a] -> a
at C:\\Users\XY\Desctop\XY.hs:30:1-32
* In the expression: []
In an equation for `find2': find2 p [] = []
* Relevant bindings include
p :: a -> Bool
(bound at C:\\Users\XY\Desctop\XY.hs:31:7)
find2 :: (a -> Bool) -> [a] -> a
(bound at C:\\Users\XY\Desctop\XY.hs:31:1)
There is a problem here. There might not be a value in your list for which p holds true. You can see that problem in the base case of your function, when you return an empty list. However, you declared your function to return a single a value, and not a list.
Because of that, you need a way to differentiate a found value from an empty value. For this you can declare your function to return Maybe a instead of a. That way, when you reach the empty list case, you can return Nothing, and if you find the element you were looking for you can return Just x. It would look like this:
find2 :: (a -> Bool) -> [a] -> Maybe a
find2 p [] = Nothing
find2 p (x:xs)
|p x = Just x
|otherwise = find2 p xs
If you're not familiar with the Maybe type, you can read more about it here
If you're ok with erroring when the list contains no satisfactory elements, you can do this:
find p xs = head (filter p xs)
or the equivalent point-free, which I like more
find p = head . filter p
(not this though, it's over the top)
find = (head .) . filter -- obscure, not a good choice
If you want to return it in a Maybe, you can import Data.Maybe and do this:
find p = listToMaybe . filter p
If you want it in a list, this never errors:
find p = take 1 . filter p
You can use dropWhile (not . p) instead of filter p if you like, too.
Manually defining the recursion is fine too, but I think it's work that isn't necessary.

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