I need a function that checks a condition on a list.
For example:
countP :: [a] -> (a -> Bool) -> Int
with the input:
countP [1,-2,0,-1,5] (>0)
should return 2, because there are two numbers greater than zero.
Here's what i've done so far:
countP :: [a] -> (a -> Bool) -> Int
countP [] _ = []
countP (x:xs) condition = if condition x then 1:countP xs condition else countP xs condition
It's returning [1,1] instead of the number two. It must be recursive.
How can i do this ?
You have to add the result, like this
countP :: [a] -> (a -> Bool) -> Int
countP [] _ = 0
countP (x:xs) condition = (if condition x then 1 else 0) + (countP xs condition)
Whenever condition x evaluates to True, we use 1 otherwise 0 and we recursively call countP and add them.
So, when you invoke it like this
countP [1, -2, 0, -1, 5] (>0)
it will be evaluated recursively, like this
(if (> 0) 1 then 1 else 0) + (countP [-2, 0, -1, 5] (> 0))
1 + (countP [-2, 0, -1, 5] (> 0))
1 + (if (> 0) -1 then 1 else 0) + (countP [0, -1, 5] (> 0))
1 + 0 + (countP [0, -1, 5] (> 0))
1 + 0 + 0 + (countP [-1, 5] (> 0))
1 + 0 + 0 + 0 + (countP [5] (> 0))
1 + 0 + 0 + 0 + 1 + (countP [] (> 0))
1 + 0 + 0 + 0 + 1 + 0 = 2
(countP [] (> 0)) is evaluated to be 0 because of our base condition of our recursive function countP [] _ = 0. It means that no matter what the second parameter is, if the first parameter is an empty list, then return 0.
You seem to be over thinking this. You can use some of the Prelude provided functions and compose them to produce the result:
length $ filter (>0) [1,-2,0,-1,5]
length will take a list and tell you how long it is.
filter takes a predicate and tells you how many elements in a provided list match that predicate.
So if you get the length of the filtered list, you are set.
countP xs f = length $ filter f xs
There is a function specifically for counting the number of things in a list, and it's called length. You could do something like
countP' [] _ = []
countP' (x:xs) condition = if condition x then 1 : countP' xs condition else countP' xs condition
countP xs condition = length (countP' xs condition)
However, this takes two functions and it does extra work. Instead you could work directly with Ints instead of [Int]s:
countP :: [a] -> (a -> Bool) -> Int
countP [] _ = 0
countP (x:xs) condition = ...
I'll still let you fill in the blanks here, know that you are not very far from the correct solution with what you already have.
However, if I were going to implement this code in a project, I would simply reach for length and filter:
countP xs condition = length (filter condition xs)
This is what I would call the idiomatic definition (up to argument order).
Related
I have just started learning Haskell and I am trying to write some basic functions in order to get a better understanding of this language.
I want to write a function which takes a list and an Int (N) as argument and returns the element at index N in the list, without using the !! operator or any built-in function.
Here is what I tried :
myHead :: [a] -> a
myHead (x:_) = x
myHead [] = error "head: empty list"
myNth :: [a] -> Int -> a
myNth x i = if i < 0
then error "nth: index can't be negative"
else myNthIterator x i 0
myNthIterator :: [a] -> Int -> Int -> a
myNthIterator [] i n = error "nth: bad index"
myNthIterator (_:x) i n = if i == n
then myHead x
else myNthIterator x i ( n + 1 )
It works but it's shifted to the right. For example myNth [1, 2, 3, 4] 2 would give 4 and not 3.
From what I understand, (_:x) removes the first element of the list and I don't see how to iterate through the list element by element.
Could someone put me on the trail? I find it difficult to find resources for beginners in this language.
We can use Maybe to model whether the index was valid.
nth :: Int -> [a] -> Maybe a
nth 0 (x : _) = Just x
nth n (x : xs) = nth (n - 1) xs
nth _ [] = Nothing
We can pattern match on the index to get our base case, and the list to get the first element and tail.
What you're doing there with (_:x) is called "pattern matching" in case you didn't know. The general pattern for iterating through a list would be (x : xs) where x is head element of the list being matched and xs is the rest of the list. If you use _ you don't remove anything it is still matched to _ which is the convention for saying "I won't use this".
With that you can make a function like this:
myNth :: [a] -> Int -> a
myNth [] _ = error "out of range"
myNth (x : xs) 0 = x
myNth (_ : xs) n = myNth xs (n - 1)
Whenever myNth is called it will go top to bottom over those definitions trying to match the patterns to the input. So when you call myNth [10,11] 1 it won't match the first clause because [10,11] doesn't match an empty list, it won't match the second either because 1 is not 0 and so it will match the third case where it will match the [10,11] on (10 : [11]), therefore _ is 10 and xs is [11] and 1 will be matched as n. Then it calls itself recursively, as myNth [11] 0. Now that will match the second case and it will return x from the match of [11] on (11 : [])
Like 414owen said you can use the Maybe a type to avoid using error.
P.S.: I don't know how beginner you are but I assume you know of the : operator, it prepends an element to a list... If you go more in depth (afaik) every list is actually stored as a sequence of a:(b:(c:(d:(e:[])))) which is equivalent to [a,b,c,d,e] which is equivalent to a:[b,c,d,e] etc.
It works but it's shifted to the right. For example myNth [1, 2, 3, 4] 2 would give 4 and not 3.
myNthIterator (_:x) i n = if i == n
then myHead x
else myNthIterator x i ( n + 1 )
Let us look at myNthIterator [1..4] 1 1
myNthIterator [1..4] 1 1 -- replace [a, b] with (a: (b : []))
== myNthIterator (1 : [2, 3, 4]) 1 1
-- matching with `myNthIterator (_:x) i n` will result in
-- 1 ~ _
-- x ~ [2, 3, 4]
-- i ~ 1
-- n ~ 1
== if 1 == 1 then myHead [2, 3, 4] else myNthIterator [2, 3, 4] 1 (1 + 1)
== myHead [2, 3, 4]
== 2
So (_:x) matching against (1 : [2, 3, 4]) is suspicious. A first step in fixing it is to replace (_:x) by (x:xs).
myNthIterator (x:xs) i n = ...
In our example this would mean x == 1 and xs == [2, 3, 4].
So I have to make a decimal number into binary list like so: intToBitString 4 = [1,0,0].
Which i have done like so:
intToBitString n = reverse (helper n)
helper 0 = []
helper n
| n `mod` 2 == 1 = 1 : helper (n `div` 2)
| n `mod` 2 == 0 = 0 : helper(n `div` 2)
But then I also have to make a function called intToByte, which pads out the list with 0-s until it's length is 8 elements long. (so making it a bytestring) Like this:
intToByte 7 = [0, 0, 0, 0, 0, 1, 1, 1]
I have tried so many things, but they never work. I am a beginner, so I only know the "if" loop the way I showed above, and recursion, but I dont know anything fancy. One of my tries:
intToByte 0 = [0]
intToByte n
| eight n == helper2 n = reverse (helper2 n)
| otherwise = eight n
helper2 0 = []
helper2 n
| n `mod` 2 == 1 = 1 : helper2 (n `div` 2)
| n `mod` 2 == 0 = 0 : helper2 (n `div` 2)
eight n
| length (helper2 n) < 8 = 0 : eight n
| otherwise = helper2 n
I have been working on this for so many hours that i'm getting confused by it. But this is part of an important assignment, so help would be very appreciated!
First of all, you can simplify your code with:
helper2 :: Integral i => i -> [i]
helper2 0 = []
helper2 n = r : helper2 q
where (q,r) = quotRem n 2
Secondly, the above is a big endian representation [wiki]. Indeed, 7 is represented as [1,1,1], whereas 14 is for example represented as [0,1,1,1]. If we want to revers this, we can work with an accumulator:
helper2 :: Integral i => i -> [i]
helper2 = go []
where go rs 0 = rs
go rs n = go (r:rs) q
where (q,r) = quotRem n 2
This thus maps 7 to [1,1,1] and 14 to [1,1,1,0]. But now we still need to add leading zeros. We can do that for example by maintaing the number of elements already added to the list:
eight :: Integral i => i -> [i]
eight = go [] 0
where go rs l 0 = replicate (8-l) 0 ++ rs
go rs l n = go (r:rs) (l+1) q
where (q,r) = quotRem n 2
Padding can be as simple as computing how many additional elements to push to the list and then have those elements produced using the function replicate from the Prelude:
padLeft :: Int -> a -> [a] -> [a]
padLeft n x xs = replicate (n - length xs) x ++ xs
For instance:
> padLeft 8 0 [1, 1, 0]
[0,0,0,0,0,1,1,0]
One approach would be to define a function bits such that bits k converts its argument to a bit string of length k:
bits :: Int -> Int -> [Int]
bits 0 _n = []
bits k n | n < 0 = error "bits: negative"
| n > 2 * m - 1 = error "bits: overflow"
| otherwise = let (i, j) = n `divMod` m in i : bits (k - 1) j
where m = 2 ^ (k - 1)
Your function eight is then easily written as
eight :: Int -> [Int]
eight = bits 8
This gives:
> eight 4
[0,0,0,0,0,1,0,0]
> eight 7
[0,0,0,0,0,1,1,1]
I have a list of 9 integers with values 1, -1, 0 such as:
[-1, 0, 0, 1, -1, -1, 1, 1, 0]
What I am trying to do is that from this one list create list of lists where each one of them contain only one change and all the time different. For each -1 I want to change it into 0.
Example:
From the list:
[-1,0,0,1,-1,-1,1,1,0],
I want to get the result:
[ [ 0, 0, 0, 1, -1, -1, 1, 1, 0]
, [-1, 0, 0, 1, 0, -1, 1, 1, 0]
, [-1, 0, 0, 1, -1, 0, 1, 1, 0]
]
So each list has only one value changed and each has a different one. I have no idea how to even start.
First thing you always need is to figure out the type signature of your function. In your case you want
lister :: [Int] -> [[Int]]
Then, as you want to loop through the list but keeping track of the indexes you have changed, an easy way would be to list a list of your list (hard to follow, just look at the code) and then zip it with its index. Then for each list you switch the element in that position. This is you code
lister :: [Int] -> [[Int]]
lister ls = [switch i l | (i,l) <- zip [0..9] (repeat ls)]
You then need a switch function, to switch the element in the ith position accordingly to your rule:
switch :: Int -> [Int] -> [Int]
switch 0 ls = ls
switch n ls = [if i == n && x == -1 then 0 else x | (i,x) <- zip [1..] ls]
Note that this returns 9 lists, one for each element in your original list. Therefore it contains some duplicates. You can eliminate them using nub from Data.List, watch out because it is O(n^2)
This is your complete code:
import Data.List
lister :: [Int] -> [[Int]]
lister ls = nub [switch i l | (i,l) <- zip [0..9] (repeat ls)]
switch :: Int -> [Int] -> [Int]
switch 0 ls = ls
switch n ls = [if i == n && x == -1 then 0 else x | (i,x) <- zip [1..] ls]
Clearly this is a very specific problem. It is often useful to look at the bigger picture: what more general problem is this a special case of? Clearly, here, we are looking through a list, and may see an element that we wish to replace, in zero or more ways. Further, we wish to see how many ways it is possible to make a limited number of such replacements. So, let us implement the general case before thinking about how to specialize to our original problem:
import Control.Applicative (Alternative, empty, (<|>))
replaceNTimes :: Alternative f => (a -> f a) -> Int -> [a] -> f [a]
replaceNTimes _ 0 xs = pure xs
replaceNTimes _ _ [] = empty
replaceNTimes f n (x:xs) = replaceHere <|> keepLooking
where replaceHere = (:) <$> f x <*> replaceNTimes f (n - 1) xs
keepLooking = (x:) <$> replaceNTimes f n xs
If we have a "budget" of zero replacements remaining, we simply return the remainder of the list. If we have budget remaining but the list is empty, we abort, because we failed to make the expected number of replacements. Otherwise, we consult our replacement-suggester function to see which replacements are legal at the current position, and choose to either make one of them and recurse with a smaller N, or to make none and recurse with the same N.
With this tool at our disposal, the original problem is easy: we just specialize N to 1 (make exactly one replacement), and supply a replacing function that only suggests replacing -1 with 0:
replaceSingleNegativeOneWithZero :: [Int] -> [[Int]]
replaceSingleNegativeOneWithZero = replaceNTimes go 1
where go (-1) = [0]
go _ = []
And test to ensure that we get the expected output:
*Main> replaceSingleNegativeOneWithZero [-1,0,0,1,-1,-1,1,1,0]
[ [0,0,0,1,-1,-1,1,1,0]
, [-1,0,0,1,0,-1,1,1,0]
, [-1,0,0,1,-1,0,1,1,0]]
Another try:
zeros :: [Int] -> [Int] -> [[Int]]
zeros _ [] = []
zeros h (x:xs) = [h ++ newX:xs] ++ zeros nextH xs
where newX = if x == (-1) then 0 else x
nextH = h ++ [x]
switch xs = ((filter (/= xs)) . (zeros [])) xs
Usage:
main = print $ switch [-1, 0, 0, 1, -1, -1, 1, 1, 0]
Hi I have the following code:
let f n (xs) = if n < 0 then f (n-1) (n:xs) else xs
f (-3) [] !! 1
and I expect it to print -4
But it does not print anything and keeps calculation in background.
What is wrong with my code?
Let's step through the evaluation:
f (-3) []
f (-4) [-3]
f (-5) [-4, -3]
f (-6) [-5, -4, -3]
f (-7) [-6, -5, -4, -3]
...
Considering this, what do you expect f (-3) [] !! 1 to be? The value in the index 1 changes each iteration, so there's no way Haskell can know what it is until it reaches the non-recursive case at n >= 0, which never happens.
If you build the list in the other direction, it will work as you expect:
let f n = if n < 0 then n : f (n - 1) else []
> f (-3) !! 1
-4
So here's a pretend integer type:
data Int2 = ... -- 2 bit signed integers [-2, -1, 0, 1]
deriving (Num, Ord, Eq, ...)
Let's imagine that your function was defined on Int2 values:
f :: Int2 -> [Int2] -> [Int2]
f n (xs) = if n < 0 then f (n-1) (n:xs) else xs
This makes it fairly easy to work out what one evaluation step looks like for f n xs:
f 1 xs = xs
f 0 xs = xs
f (-1) xs = f (-2) (-1 : xs)
f (-2) xs = f 1 (-2 : xs) -- because finite signed arithmetic wraps around
and from there we can work out the full value of f n []:
f 1 [] = []
f 0 [] = []
f (-1) [] = f (-2) [-1] = f 1 [-2, -1] = [-2, -1]
f (-2) [] = f 1 [-2] = [-2]
Each computed a value, but note how it took 3 evaluation steps before we got a list out of f (-1) [].
Now see if you can work out how many steps it would take to compute f (-1) [] if it were defined on 4-bit numbers. 8-bit? 32-bit? 64-bit? What if it were using Integer which has no lower bound?
At no point does laziness help you because there's no partial result, only a recursive call. That's the difference between:
lazyReplicate 0 _ = []
lazyReplicate n x = x : lazyReplicate (n - 1) x
and
strictReplicate n x = helper [] n x where
helper xs 0 _ = xs
helper xs n x = helper (x : xs) n x
I'm trying to look for pairs of elements in a list, assuming that they are the only pair in the list, and there are no more than 3 identical consecutive elements.
I have a function that takes in a list, and returns the index of the first element of the pair, if there is any. If not, then it returns -1
searchForPairs xs = searchHelp xs ((genericLength xs) - 1)
where searchHelp xs n
| searchHelp xs 0 = -1 -- no pairs found
| (xs !! n) == (xs !! (n - 1)) = n
| otherwise = searchHelp xs n-1
For some reason, it is returning the error:
Couldn't match expected type `Bool' with actual type `Int'
In the expression: n
In an equation for `searchHelp':
searchHelp xs n
| searchHelp xs 0 = - 1
| (xs !! n) == (xs !! (n - 1)) = n
| otherwise = searchHelp xs n - 1
In an equation for `searchForPairs':
searchForPairs xs
= searchHelp xs ((genericLength xs) - 1)
where
searchHelp xs n
| searchHelp xs 0 = - 1
| (xs !! n) == (xs !! (n - 1)) = n
| otherwise = searchHelp xs n - 1
It seems like it should work. Any ideas why it is not?
#gereeter already explained your errors, I would just like to point out that you should not return -1 in case the answer is not found. Instead, you should return Nothing if there is no answer and Just pos if the answer is pos. This protects you from many kinds of errors.
I couldn't quite grok what you want to do, but from the code, it looks like you're trying to find two consecutive elements in a list that are equal. Instead of using !! to index the list, you can use pattern matching to extract the first two elements of the list, check if they are equal, and continue searching the remainder (including the second element) if they are not. If the list doesn't have at least two elements, you return Nothing
searchForPairs xs = go 0 xs where
go i (x1:xs#(x2:_)) | x1 == x2 = Just i
| otherwise = go (i+1) xs
go _ _ = Nothing
You have two problems. The first is in this line:
| otherwise = searchHelp xs n-1
The compiler interperets this as (searchHelp xs n) - 1, not searchHelp xs (n-1), as you intended. The second problem is in you use of guards:
| searchHelp xs 0 = -1 -- no pairs found
Since searchHelp xs 0 is not a boolean expression (you wanted to use it as a pattern), the compiler rejected it. I can see two easy solutions:
searchForPairs xs = searchHelp xs ((genericLength xs) - 1)
where searchHelp xs n
| n == 0 = -1 -- no pairs found
| (xs !! n) == (xs !! (n - 1)) = n
| otherwise = searchHelp xs (n-1)
and
searchForPairs xs = searchHelp xs ((genericLength xs) - 1)
where
searchHelp xs 0 = -1 -- no pairs found
searchHelp xs n
| (xs !! n) == (xs !! (n - 1)) = n
| otherwise = searchHelp xs (n-1)
Now, unfortunately, although this works, it is terribly inefficient. This is because of your use of !!. In Haskell, lists are linked lists, and so xs !! n will take n steps, instead of 1. This means that the time your function takes is quadratic in the length of the list. To rectify this, you want to loop along the list forward, using pattern matching:
searchForPairs xs = searchHelp xs 0 where
searchHelp (x1 : x2 : xs) pos
| x1 == x2 = pos
| otherwise = searchHelp (x2 : xs) (pos + 1)
searchHelp _ _ = -1
For what it's worth, here is a somewhat idiomatic (and point-free) implementation of what you are trying to do:
searchPairs :: Eq a => [a] -> Maybe Int
searchPairs = interpret . span (uncurry (/=)) . (zip <*> tail)
where
interpret (flag, res) = if null flag then Nothing else Just $ length res
Explanation: zip <*> tail creates a list of pairs of successive elements (using the reader Applicative type class). uncurry (/=) tests if such a pair is made of identical elements. Finally, interpret translates the result in a value of Maybe Int type.