How can I solve this haskell function? - list

Specify the function that decides from a list whether it contains 0!
How can I fix this ?
hasZero :: [Int] -> Bool
hasZero (0) = True
hasZero _ = False

Use pattern matching and call the function recursively while always checking the element at head for being zero and passing the rest down the recursive stack if it is not. If you find a zero, the function returns early with a True. If not, it recourses the whole list and returns False once it hits the empty list base case.
hasZero :: [Int] -> Bool
hasZero [] = False
hasZero (0:_) = True
hasZero (x:xs) = hasZero xs

The simplest solution is making use of elem :: (Foldable f, Eq a) => a -> f a -> Bool. In that case we can implement this as:
hasZero :: [Int] -> Bool
hasZero xs = 0 `elem` xs
or simpler:
hasZero :: [Int] -> Bool
hasZero = elem 0
We can also make use of any :: Foldable f => (a -> Bool) -> f a -> Bool:
hasZero :: [Int] -> Bool
hasZero = any (0 ==)
or we can work with recursion and perform pattern matching like in #user1984's answer:
hasZero :: [Int] -> Bool
hasZero (0:_) = True
hasZero (_:xs) = hasZero xs
hasZero [] = False

Related

Haskell how to drop all 0 of the list until one of the elements /= 0?

I'm new to Haskell and I'm trying to figure out how to write a code, that drops all zeros until an element of the list is >0.
So for example:
Input: [0,0,5,6,0]
Output: [5,6,0]
So far I have wrote this:
zeroUntil :: [Int] -> [Int]
zeroUntil [] = []
zeroUntil (x:xs)
| x == 0 = drop x (xs)
| otherwise = zeroUntil xs
But somehow intead of [5,6,0] i get [ ].
Can anybode please explain what did I do wrong?
You can make use of dropWhile :: (a -> Bool) -> [a] -> [a] and thus drop items as long as these are zeros:
zeroUntil :: [Int] -> [Int]
zeroUntil = dropWhile (0 ==)
If you want to drop zeros until an element is greater than zero, you can make use of recursion. Here your recursive case should yield elements if these are less than zero:
zeroUntil :: [Int] -> [Int]
zeroUntil [] = []
zeroUntil (0:xs) = zeroUntil xs
zeroUntil (x:xs)
| x > 0 = x : xs -- ← end of recursion, return the list
| otherwise = x : zeroUntil xs -- ← yield x and recurse
for example:
Prelude> zeroUntil [0,0,5,6,0]
[5,6,0]
Prelude> zeroUntil [0,-1,5,6,0]
[-1,5,6,0]
zeroUntil :: [Int] -> [Int]
zeroUntil [] = []
zeroUntil (x:xs)
| x == 0 = drop x (xs)
| otherwise = [x] ++ (zeroUntil xs)
You have to add the first element (x) to the list returned by the recursive call, otherwise you return a empty list.

Breaking up a list into sublists with recursion

I'm trying to write a function with the type declaration [(Int, Bool)] -> [[Int]]. I want the function to only add Ints to the same nested sublist if the Boolean is True. However if the Boolean is False, I want the Int associated with the next True bool to be added to a new sublist. For example: An input of
[(1,True),(2,True),(3,False),(4,True),(5,False),(6,False),(7,True)]
should return
[[1,2],[4],[7]].
My code so far:
test:: [(Int, Bool)] -> [[Int]]
test xs = case xs of
[]->[]
x:xs
| snd x == True -> [(fst x)] : test xs
| snd x == False -> test xs
I'm currently having issues on adding concurrent Ints to the same list if their bools are both True.
You can break this problem into two sub-problems.
For any given list, take the head of this list and match it against the rest of list. There are two possibilities during this matching: i) You are successful i.e. you match, and if so, you collect the matched value and continue looking for more values, or ii) You fail, i.e. you don't match, and if so, you stop immediately and return the so far matched result with rest of, not-inspected, list.
collectF :: (Eq a) => (a -> Bool) -> [a] -> ([a], [a])
collectF f [] = ([], [])
collectF f (x : xs)
| f x = let (ys, zs) = collectF f xs in (x : ys, zs)
| otherwise = ([], x : xs)
Now that you have the collectF function, you can use it recursively on input list. In each call, you would get a successful list with rest of, not-inspected, list. Apply collectF again on rest of list until it is exhausted.
groupBy :: (Eq a) => (a -> a -> Bool) -> [a] -> [[a]]
groupBy _ [] = []
groupBy f (x : xs) =
let (ys, zs) = collectF (f x) xs in
(x : ys) : groupBy f zs
*Main> groupBy (\x y -> snd x == snd y) [(1,True),(2,True),(3,False),(4,True),(5,False),(6,False),(7,True)]
[[(1,True),(2,True)],[(3,False)],[(4,True)],[(5,False),(6,False)],[(7,True)]]
I am leaving it to you to remove the True and False values from List. Also, have a look at List library of Haskell [1]. Hope, I am clear enough, but let me know if you have any other question.
[1] http://hackage.haskell.org/package/base-4.12.0.0/docs/src/Data.OldList.html#groupBy
Repeatedly, drop the Falses, grab the Trues. With view patterns:
{-# LANGUAGE ViewPatterns #-}
test :: [(a, Bool)] -> [[a]]
test (span snd . dropWhile (not . snd) -> (a,b))
| null a = []
| otherwise = map fst a : test b
Works with infinite lists as well, inasmuch as possible.
Here's how I'd write this:
import Data.List.NonEmpty (NonEmpty(..), (<|))
import qualified Data.List.NonEmpty as NE
test :: [(Int, Bool)] -> [[Int]]
test = NE.filter (not . null) . foldr go ([]:|[])
where
go :: (Int, Bool) -> NonEmpty [Int] -> NonEmpty [Int]
go (n, True) ~(h:|t) = (n:h):|t
go (n, False) l = []<|l
Or with Will Ness's suggestion:
import Data.List.NonEmpty (NonEmpty(..))
test :: [(Int, Bool)] -> [[Int]]
test = removeHeadIfEmpty . foldr prependOrStartNewList ([]:|[])
where
prependOrStartNewList :: (Int, Bool) -> NonEmpty [Int] -> NonEmpty [Int]
prependOrStartNewList (n, True) ~(h:|t) = (n:h):|t
prependOrStartNewList (n, False) l = []:|removeHeadIfEmpty l
removeHeadIfEmpty :: NonEmpty [Int] -> [[Int]]
removeHeadIfEmpty (h:|t) = if null h then t else h:t

Determining if there are repeated elements in a list in Haskell

I'm trying to test lists for duplicates but when I compile and enter
repeated [1,2,3,4]
it outputs True. What's wrong?
belongs :: Eq a => a -> [a] -> Bool
belongs n [] = False
belongs n (x:xs) | n == x = True
| otherwise = belongs n xs
repeated :: [Integer] -> Bool
repeated [] = False
repeated (x:xs) | belongs x xs = True
| otherwise = belongs (head xs) xs
"belongs (head xs) xs" checks whether xs's head is within xs, which will always be true.
(Except when xs is empty, in which case your program will crash! "head" is a partial function, crashes with empty lists)
This would fix it (as pointed by #talex too, but I also suggest making it more general, there is no need to specialize it to Integer):
repeated :: Eq a => [a] -> Bool
repeated [] = False
repeated (x:xs) | belongs x xs = True
| otherwise = repeated xs
You want
repeated :: [Integer] -> Bool
repeated [] = False
repeated (x:xs) | belongs x xs = True
| otherwise = repeated xs

Replicating through a list in Haskell

replicatee :: [a] -> Int -> [a]
replicatee [] _ = []
replicatee xs 0 = []
replicatee (x:xs) n = x:replicatee (x:xs) (n-1): replicatee xs n
So this is my code for replicating a an element in a list n times, the compler keeps showing an error :
Couldnt match type 'a'with [a], I'm seriously confused, please help out.
Edit : what i want my function to do is this:
replicatee [1,2,3,4] 2
[1,1,2,2,3,3,4,4]
I might have misunderstood your intention, but maybe you meant something like this:
replicatee :: a -> Int -> [a]
replicatee _ 0 = []
replicatee x n = x:replicatee x (n-1)
replicatee :: [a] -> Int -> [a]
replicatee [] _ = []
replicatee xs 0 = []
replicatee (x:xs) n = x:replicatee (x:xs) (n-1): replicatee xs n
The problem is that replicatee returns a value of type [a], but you try to add that to another list of type [a] using (:) :: a -> [a] -> [a]. From a type-checking perspective, you need to use (++), not (:):
replicatee xs'#(x:xs) n = x : (replicatee xs' (n-1) ++ replicatee xs n)
Whether it does what you intended is another matter. Based on your description, Mikkel provides the right answer.

Haskell: Check if the first list is a prefix of the second

I am trying to write a program that checks if the first list is a prefix of the second list. for example, [5,6] is prefix of [1,5,6,7]. here is my working code but basically I don't have an idea on how to do it.
prefix [Int] -> [Int] -> Bool
prefix [] [] = []
prefix y (x:xs)
| x == y = prefix y xs
| otherwise = 0
any help please ?
Your code does not make much sense if we look at the types:
prefix [Int] -> [Int] -> Bool
prefix [] [] = []
prefix y (x:xs)
| x == y = prefix y xs
| otherwise = 0
Since the two arguments are lists ([Int]), this thus means that y is an [Int], x is an Int, and xs is an [Int]. But then you compare x == y, you can not compare a list with an element. (==) is defined as (==) :: Eq a => a -> a -> Bool.
There are also other problems here: you return a list in the first clause, but the return type is a Bool, and later you return a 0 (again, it should be a Bool).
In case we define a function, we first need to define a certain model for it. When is a list l1 a prefix of a list l2? In case l1 is an empty list, then l1 is always a prefix, regardless of the value of the second list, so:
prefix [] _ = True
In case l1 is a list (i.e. (x:xs)), then it is not a prefix in two cases: (1) in case l2 is an empty list; and (2) in case the first item of l2 (y in (y:ys)) is not equal to x, so:
prefix _ [] = False
prefix (x:xs) (y:ys) | x /= y = False
| otherwise = ...
Now the question is what to do with prefix (x:xs) (y:ys) in case x == y. In that case we recurse on the two list, so the result of prefix (x:xs) (y:ys) == prefix xs ys (only in case x == y), so:
| otherwise = prefix xs ys
Or now in full:
prefix :: [Int] -> [Int] -> Bool
prefix [] _ = True
prefix _ [] = False
prefix (x:xs) (y:ys) | x /= y = False
| otherwise = prefix xs ys
We can further generalize the expression to Eq a => [a] -> [a] -> Bool such that it works with any type a that is an Eq instance (so there is a (==) instance defined over a):
prefix :: Eq a => [a] -> [a] -> Bool
prefix [] _ = True
prefix _ [] = False
prefix (x:xs) (y:ys) | x /= y = False
| otherwise = prefix xs ys
We can also swap the conditions, since usually positive logic is easier to understand than negative logic:
prefix :: Eq a => [a] -> [a] -> Bool
prefix [] _ = True
prefix _ [] = False
prefix (x:xs) (y:ys) | x == y = prefix xs ys
| otherwise = False
now we can furthermore remove the guards, and use an (&&) :: Bool -> Bool -> Bool instead:
prefix :: Eq a => [a] -> [a] -> Bool
prefix [] _ = True
prefix _ [] = False
prefix (x:xs) (y:ys) = x == y && prefix xs ys
Just leaving my two cents here with a combination of functions from Prelude:
isPrefix :: Eq a => [a] -> [a] -> Bool
isPrefix l1 l2 = take (length l1) l2 == l1