haskell Own version of Elem function using Foldl - haskell

I'm trying to create my own version of elem function, which returns True or False based on if the element x is inside the given array.
elem' :: Eq(t)=>t->[t]->Bool
elem' x xs = or [foldl (\acc -> \a -> if a == x then True else False) [] xs]
What I'm trying to do here is to fill the array using foldl with True/False values and then make or function, which returns True if at least one of them is True (so what I want to get). However, this code results in the following compilation error:
main.hs:11:71: error:
* Couldn't match expected type `Bool' with actual type `[a0]'
* In the second argument of `foldl', namely `[]'
In the expression:
foldl (\ acc -> \ a -> if a == x then True else False) [] xs
In the first argument of `or', namely
`[foldl (\ acc -> \ a -> ...) [] xs]'
|
11 | elem' x xs = or [foldl (\acc -> \a -> if a == x then True else False) [] xs]
|
^^

The idea of using a foldl is not to make a list of elements, and thus not to use or.
If you make use of foldl, then in case a == x fails, you look if the elem on the previous elements was succesful, so we return acc in that case. Furthermore you can not use [] as the "start value" for the accumulator, since the foldl is supposed to return a Bool, not a list:
elem' :: (Foldable f, Eq t) => t -> f t -> Bool
elem' x xs = foldl (\acc a -> if a == x then True else acc) False xs
Here it is however not a good idea to use foldl, since that means we will enumerate over the entire list. If we make use of foldr, we can stop from the moment we have found an element, so we can rewrite this to:
elem' :: (Foldable f, Eq t) => t -> f t -> Bool
elem' x = foldr (\e -> if x == e then const True else id) False
If we thus check:
elem' 1 ([1,4,2,5] ++ repeat 3)
It will return True for the foldr approach, whereas it will loop for the foldl approach.

Related

Trying to code my own 'partition' function in haskell

as the title says, I'm trying to recode this function but I keep getting an error that says that the type that I output doesnt match the expected type. Could someone help me with this? Here's my code :
myPartition :: (a -> Bool) -> [a] -> ([a], [a])
myPartition f (x:xs) = if f x
then (x : myPartition f xs, [])
else ([], x : myPartition f xs)
myPartition _ [] = ([], [])
Also, im not authorized to use any function of the standard library
The main problem is that your function checks if f x holds, and if so constructs a 2-tuple where it will write the entire result of the recursive call. That result will be a 2-tuple as well, so you try to use a 2-tuple as an element in a 2-tuple as an element in a …
You should make a recursive call to obtain a 2-tuple of elements for the rest of the list, and the prepend the item to any of the two, so:
myPartition :: (a -> Bool) -> [a] -> ([a], [a])
myPartition p = go
where go (x:xs)
| p x = (…, …)
| otherwise = (…, …)
where (pa, pb) = go xs
go [] = ([], [])
where you still need to fill in the … parts.

HASKELL The lambda expression ‘\ xs -> ...’ has one argument, but its type ‘[t]’ has none

We had to write lambda function in Haskell but it always shows errors. What do I do wrong? all codes have the same kind of error, but I don't understand how to make them right.
length' :: [a] -> [a] -> Int
length' [] = 0
length' (x:xs) (y:ys) = \n -> if length (x:xs) > (y:ys) then 1 else if (x:xs) == (y:ys) then 0 else if (x:xs) < (y:ys) then -1
find :: a -> [a] -> Bool
find p [] = False
find p xs = \p -> if p `elem` xs then True else False
remove y [] = []
remove y (x:xs) = \xs -> if y == x then xs else x: remove y xs
• Couldn't match expected type ‘Bool’ with actual type ‘a -> Bool’
• The lambda expression ‘\ p -> ...’ has one argument,
but its type ‘Bool’ has none
In the expression: \ p -> if p `elem` xs then True else False
In an equation for ‘find’:
find p xs = \ p -> if p `elem` xs then True else False
the errors are the same
Couldn't match expected type ‘[t]’ with actual type ‘[t] -> [t]’
• The lambda expression ‘\ xs -> ...’ has one argument,
but its type ‘[t]’ has none
In the expression: \ xs -> if y == x then xs else x : remove y xs
In an equation for ‘remove’:
You have a problem with this function:
find :: a -> [a] -> Bool
find p [] = False
find p xs = \p -> if p `elem` xs then True else False
By its type declaration, it takes a value of the type a, a list of values, also all of the type a, and returns a Bool.
In the find case that matches on p and xs, the compiler must accept the type declaration, so p must be of the type a, and xs must be of the type [a]. This means that the return value must be Bool.
The expression, however, returns a lambda expression. That particular lambda expression has the type Eq a => a -> Bool. You can try that in GHCi:
Prelude> xs = undefined :: [a]
Prelude> :t \p -> if p `elem` xs then True else False
\p -> if p `elem` xs then True else False :: Eq a => a -> Bool
You can fix the problem by not returning a function, i.e. not returning a lambda expression.
Unfortunately there are many mistakes: I'll only point out the first ones.
length' :: [a] -> [a] -> Int
This states that length' takes two arguments of type [a] and returns an Int. This is weird: why a length function takes two lists? Let's assume two arguments is indeed what you want and move on.
length' [] = 0
Here you define length' having a single argument []. Why not two?
length' (x:xs) (y:ys) = \n -> ...
Here you define length having two arguments, x:xs and y:xs. However, you return a function \n -> ... and that does not match with the Int return type.
Moreover:
length (x:xs) > (y:ys)
above you compare an Int and a list. Is,say, 5 < [1,2,3] true? No, it's a meaningless comparison.

Writing overlaps function

I want to write a polymorphic function that inputs two lists and tells me whether these two lists contain a common element. My attempt at writing this function is as follows:
overlaps :: (Eq a) => [a] -> [a] -> Bool
overlaps x:xs y:ys
| x `is_element_of` ys = True
| otherwise = False
where
is_element_of :: (Eq a) => a -> [a] -> Bool
is_element_of e list = case list of
[] -> False
x: xs -> e == x || e `is_element_of` xs
However this isn't working... Is it possible to pattern match against two lists? Is this a possible way of writing this function?
Your function is_elem_of already exists in the Data.List package as elem. Using that, overlaps is easy to write.
overlaps [] _ = False
overlaps (x:xs) ys = x `elem` ys || overlaps xs ys
As you can tell, it is possible to pattern match on lists. If you want to write the function without pattern matching on lists, you can use the foldr function.
overlaps xs ys = foldr (\x acc -> x `elem` ys || acc) False xs
I think you would want something like this (untested):
overlaps :: (Eq a) => [a] -> [a] -> Bool
overlaps [] _ = False
overlaps _ [] = False
overlaps (x:xs) list = x `myelem` list || overlaps xs list
myelem :: (Eq a) => a -> [a] -> Bool
myelem _ [] = False
myelem x (y:ys) = x == y || myelem x ys
AFAIK using the pattern matching appropach is more idiomatic.

How do I find an element in an infinite list using the foldr function in Haskell?

I'm trying to create a new implementation of the elem function in Haskell using the foldr function.
So far I have this:
count :: Eq a => a -> [a] -> Integer
count x (y:ys) = foldl (\counter y -> if y == x then counter + 1 else counter) 0 ys
count _ [] = 0
elem' :: Eq a => a -> [a] -> Bool
elem' x (y:ys) = foldr (\i elem-> if (count x (y:ys)) > 0 then True else False) False ys
elem' _ [] = False
The count function is counting the number of occurances of x (another function I wrote) using foldl. This works fine for finite lists, but the problem is that I want to take advantage of the foldr lazy computation of an infinite list. If I try to use an infinite list as input the program hangs forever.
Basically I want to "break out" once I find any instance of x in the list and return true, otherwise return false.
Thanks for the help.
Let's start with the basic skeleton on the foldr pattern:
elem :: Eq a => [a] -> Bool
elem x xs = foldr kons knil xs
When foldr sees [], it will return knil. Since nothing is an element of the empty list, we conclude that
knil = False
When foldr kons False sees a list a : as, it returns kons a (foldr kons False as). We can assume inductively that foldr kons False as = elem x as, so we seek to solve for kons in
elem x (a : as) = kons a (elem x as)
I bet you can finish up by coming up with the definition of kons. Watch out for Boolean short-circuit behavior to make this efficient and avoid problems with infinite lists.

Redundant if statement warning in haskell

So I'm following the tutorial Learn you a Haskell for Great Good! and so far I absolutely love Haskell. But in one of the functions mentioned in the tutorial I'm getting a warning that the if-statement is redundant.
Edit: Let me be clear, the intent of the function is to act exactly the same way the elem function works (the one that is provided with Haskell by default).
Here's the original function:
elem' :: (Eq a) => a -> [a] -> Bool
elem' y ys = foldl (\acc x -> if x == y then True else acc) False ys
Originally there were two warnings, one was eta reduction, so I removed the ys from the beginning and end of the function name to arrive at:
elem' :: (Eq a) => a -> [a] -> Bool
elem' y = foldl (\acc x -> if x == y then True else acc) False
Now I tried to reduce the function to the following and it results in an error:
elem' :: (Eq a) => a -> [a] -> Bool
elem' y = foldl (\acc x -> x == y)
I think I'm just very new to Haskell and can't see the obvious solution. Can someone tell me what code change would keep the function working correctly and yet remove the compiler warning?
if x == y then True else acc is the same as x == y || acc.
Typing your last definition into GHCi without a type annotation:
Prelude> let elem' y = foldl (\acc x -> x == y)
Prelude> :t elem'
elem' :: (Eq b) => b -> Bool -> [b] -> Bool
It doesn't match your declared type.
You forgot the False at the end! If you add it in:
Prelude> let elem' y = foldl (\acc x -> x == y) False -- note the False at the end
Prelude> :t elem'
elem' :: (Eq b) => b -> [b] -> Bool
It has the right type!

Resources