I need to display the number of elements whose successor is greater in a list. For example, in the list [3,7,2,1,9] my function should return 2 because 7 is greater than 3 and 9 is greater than 1.
In order to do that,I was thinking to use the filter function:
greaterElems :: Ord a => [a] -> Int
greaterElems [] = 0
greaterElems [x] = 0
greaterElems (x:xs) = length (filter (< head xs) (x:xs))
However, this does not work as expected: it seems that Haskell always considers the second element of the list, as if "head xs" is calculated only once, but this does not seem normal to me since Haskell is lazy.
What am I missing and how could I fix my code in order to achieve my goal?
You can make use of zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] where we pass the list, and its tail. Indeed:
sucGreater :: Ord a => [a] -> [Bool]
sucGreater x = zipWith (<) x (tail x)
or as #RobinZigmond says, we can omit tail, and use drop:
sucGreater :: Ord a => [a] -> [Bool]
sucGreater x = zipWith (<) x (drop 1 x)
For the given sample list, this gives us:
Prelude> sucGreater [3,7,2,1,9]
[True,False,False,True]
I leave it as an exercise to the count the number of Trues in that list.
Related
I have to code a function to calculate (sum k=1 to n) (-1)^(k+1) * a_k from list [a_1,a_2,a_3,..a_n] using foldl.
calculate list = foldl (\x xs ->
x + (xs * (-1)^(??? + 1))
) 0 list
I managed to write this code, but I don't have a clue what should replace ???, how to get index of an element in given list.
Thanks to comment by Willem, I managed to do this in this way:
calculate list = foldl (\x (index,el) ->
x + (el * (-1)^(1 + index))
) 0 (zip [1..length(list)] list)
For me, it's more readable one, because I'm newbie, I just posted it for others :)
We can implement this in a more simple way. We can consider a infinite list where we repeat two functions: id :: a -> a, and negate :: Num a => a -> a, and use cycle :: [a] -> [a] to construct an infinite list. So cycle [id, negate] will produce a list that looks like [id, negate, id, negate, ...].
We can then use zipWith to zip the infinite list with the list of values, and use ($) :: (a -> b) -> a -> b as "zip function", so we get:
Prelude> zipWith ($) (cycle [id, negate]) [1,4,2,5]
[1,-4,2,-5]
The finally we can use sum :: Num a => [a] -> a to sum up these values.
So we can define the function as:
calculate :: Num a => [a] -> a
calculate = sum . zipWith ($) (cycle [id, negate])
For example:
Prelude> calculate [1,4,2,5]
-6
dropnth' :: [a] -> Int -> [a]
dropnth' xs n = foldl (\a b -> if (last a) == xs!!n then a else b ++ []) [head xs] xs
I was trying to solve this "dropping every nth element of a list" question using foldl, but I'm getting an error. How can I do that?
Error:
a are presumably the elements that you have already decided not to drop. You should then decide whether to drop, not the last element of a, but the next element in xs, which is presumably b.
b ++ [] is presumably meant to express that you have decided not to drop the element b, instead adding it to the list a. This is actually written a ++ [b].
This allows me to write this piece of code, which at least compiles:
dropnth' :: Eq a => [a] -> Int -> [a]
dropnth' xs n = foldl (\a b -> if b == xs!!n then a else a ++ [b]) [head xs] xs
xs!!n finds the nth element of xs, and comparing with that will find decide whether something's value is equal to that, not something's position. Note the Eq a, which tells us that we are comparing list values. foldl will have to get the positions of the entries from somewhere, such as from zip [0..].
dropnth' :: [a] -> Int -> [a]
dropnth' xs n = foldl (\a (i, b) -> if mod i n == 0 then a else a ++ [b]) [head xs] (zip [0..] xs)
Adding an element to the end of a list has to rebuild the whole list. Building the list up from its end would be much more efficient. But in this case, we can even use more specialized list operations for our use case.
dropnth' :: [a] -> Int -> [a]
dropnth' xs n = [b | (i, b) <- zip [0..] xs, mod i n > 0]
Note that we now drop the initial element as well. Perhaps that is what you want? Or you could zip with [1..] instead to shift all the crosshairs one to the left.
Usually, type signatures like Int -> [a] -> [a] compose better.
My ultimate goal is to find if a list y contains all the elements of list x (I'm checking if x is a subset of y sort of thing)
subset x y =
and [out | z <- x
, out <- filter (==z) y ]
This doesn't work, and I know it's because z is a list still. I'm trying to make sense of this.
I think I may have to use the elem function, but I'm not sure how to split x into chars that I can compare separately through y.
I'm ashamed to say that I've been working on this simple problem for an hour and a half.
Checking whether all elements of xs are elements of ys is very straightforward. Loop through xs, and for each element, check if it is in ys:
subset xs ys = all (\x -> elem x ys) xs
You could also use the list difference function (\\). If you have list y and list x, and you want to check that all elements of x are in y, then x \\ y will return a new list with the elements of x that are not in y. If all the elements of x are in y, the returned list will be empty.
For example, if your list y is [1,2,3,4,5] and your list x is [2,4], you can do:
Prelude> [2,4] \\ [1,2,3,4,5]
[]
If list y is [1,2,3,4,5] and list x is [2,4,6], then:
Prelude> [2,4,6] \\ [1,2,3,4,5]
[6]
Easy way to reason about subsets is to use sets as the data type.
import qualified Data.Set as S
subset :: Ord a => [a] -> [a] -> Bool
subset xs ys = S.isSubsetOf (S.fromList xs) (S.fromList ys)
Then it's as simple as:
*Main> subset [1..5] [1..10]
True
*Main> subset [0..5] [1..10]
False
Let's break this down into two subproblems:
Find if a value is a member of a list;
Use the solution to #1 to test whether every value in a list is in the second one.
For the first subproblem there is a library function already:
elem :: (Eq a, Foldable t) => a -> t a -> Bool
Lists are a Foldable type, so you can use this function with lists for t and it would have the following type:
elem :: (Eq a) => a -> [a] -> Bool
EXERCISE: Write your own version of elem, specialized to work with lists (don't worry about the Foldable stuff now).
So now, to tackle #2, one first step would be this:
-- For each element of `xs`, test whether it's an element of `ys`.
-- Return a list of the results.
notYetSubset :: Eq a => [a] -> [a] -> [Bool]
notYetSubset xs ys = map (\x -> elem x ys) xs
After that, we need to go from the list of individual boolean results to just one boolean. There's a standard library function that does that as well:
-- Return true if and only if every element of the argument collection is
-- is true.
and :: Foldable t => t Bool -> Bool
EXERCISE: write your own version of and, specialized to lists:
myAnd :: [Bool] -> Bool
myAnd [] = _fillMeIn
myAnd (x:xs) = _fillMeIn
With these tools, now we can write subset:
subset :: Eq a => [a] -> [a] -> [Bool]
subset xs ys = and (map (\x -> elem x ys) xs)
Although a more experienced Haskeller would probably write it like this:
subset :: Eq a => [a] -> [a] -> [Bool]
subset xs ys = every (`elem` ys) xs
{- This:
(`elem` ys)
...is a syntactic shortcut for this:
\x -> x elem ys
-}
...where every is another standard library function that is just a shortcut for the combination of map and and:
-- Apply a boolean test to every element of the list, and
-- return `True` if and only if the test succeeds for all elements.
every :: (a -> Bool) -> [a] -> Bool
every p = and . map p
I just wanted to multiply two lists element by element, so I'd pass (*) as the first argument to that function:
apply :: Num a => (a -> a -> a) -> [a] -> [a] -> [a]
apply f xs ys = [f (xs !! i) (ys !! i) | i <- [0..(length xs - 1)]]
I may be asking a silly question, but I actually googled a lot for it and just couldn't find. Thank you, guys!
> :t zipWith
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
> zipWith (*) [1,2,3] [4,5,6]
[4,10,18]
It's the eighth result provided by Hoogle when queried with your type
(a -> a -> a) -> [a] -> [a] -> [a]
Moreover, when you need to implement your own function, use list !! index only as a last resort, since it usually leads to a bad performance, having a cost of O(index). Similarly, length should be used only when necessary, since it needs to scan the whole list.
In the zipWith case, you can avoid both and proceed recursively in a natural way: it is roughly implemented as
zipWith _ [] _ = []
zipWith _ _ [] = []
zipWith f (x:xs) (y:ys) = f x y : zipWith f xs ys
Note that this will only recurse as much as needed to reach the end of the shortest list. The remaining part of the longer list will be discarded.
Brief: This is a past exam question from a Miranda exam but the syntax is very similar to Haskell.
Question: What is the type of the following expression and what does it do? (The definitions
of the functions length and swap are given below).
(foldr (+) 0) . (foldr ((:) . length . (swap (:) [] )) [])
length [] = 0
length (x:xs) = 1 + length xs
swap f x y = f y x
Note:
Please feel free to reply in haskell syntax - sorry about putting using the stars as polytypes but i didn't want to translate it incorrectly into haskell. Basically, if one variable has type * and the other has * it means they can be any type but they must both be the same type. If one has ** then it means that it can but does not need to have the same type as *. I think it corresponds to a,b,c etc in haskell usuage.
My working so far
From the definition of length you can see that it finds the length of a list of anything so this gives
length :: [*] -> num.
From the definition I think swap takes in a function and two parameters and produces the function with the two parameters swapped over, so this gives
swap :: (* -> ** -> ***) -> ** -> [*] -> ***
foldr takes a binary function (like plus) a starting value and list and folds the list from right to left using that function. This gives
foldr :: (* -> ** -> **) -> ** -> [*] -> **)
I know in function composition it is right associative so for example everything to the right of the first dot (.) needs to produce a list because it will be given as an argument to the first foldr.
The foldr function outputs a single value ( the result of folding up the list) so I know that the return type is going to be some sort of polytype and not a list of polytype.
My problem
I'm unsure where to go from here really. I can see that swap needs to take in another argument, so does this partial application imply that the whole thing is a function? I'm quite confused!
You've already got the answer, I'll just write down the derivation step by step so it's easy to see all at once:
xxf xs = foldr (+) 0 . foldr ((:) . length . flip (:) []) [] $ xs
= sum $ foldr ((:) . length . (: [])) [] xs
= sum $ foldr (\x -> (:) (length [x])) [] xs
= sum $ foldr (\x r -> length [x]:r) [] xs
= sum $ map (\x -> length [x] ) xs
= sum [length [x] | x <- xs]
= sum [ 1 | x <- xs]
-- = length xs
xxf :: (Num n) => [a] -> n
So that, in Miranda, xxf xs = #xs. I guess its type is :: [*] -> num in Miranda syntax.
Haskell's length is :: [a] -> Int, but as defined here, it is :: (Num n) => [a] -> n because it uses Num's (+) and two literals, 0 and 1.
If you're having trouble visualizing foldr, it is simply
foldr (+) 0 (a:(b:(c:(d:(e:(...:(z:[])...))))))
= a+(b+(c+(d+(e+(...+(z+ 0)...)))))
= sum [a, b, c, d, e, ..., z]
Let's go through this step-by-step.
The length function obviously has the type that you described; in Haskell it's Num n => [a] -> n. The equivalent Haskell function is length (It uses Int instead of any Num n).
The swap function takes a function to invoke and reverses its first two arguments. You didn't get the signature quite right; it's (a -> b -> c) -> b -> a -> c. The equivalent Haskell function is flip.
The foldr function has the type that you described; namely (a -> b -> b) -> b -> [a] -> b. The equivalent Haskell function is foldr.
Now, let's see what each sub expression in the main expression means.
The expression swap (:) [] takes the (:) function and swaps its arguments. The (:) function has type a -> [a] -> [a], so swapping it yields [a] -> a -> [a]; the whole expression thus has type a -> [a] because the swapped function is applied to []. What the resulting function does is that it constructs a list of one item given that item.
For simplicity, let's extract that part into a function:
singleton :: a -> [a]
singleton = swap (:) []
Now, the next expression is (:) . length . singleton. The (:) function still has type a -> [a] -> [a]; what the (.) function does is that it composes functions, so if you have a function foo :: a -> ... and a function bar :: b -> a, foo . bar will have type b -> .... The expression (:) . length thus has type Num n => [a] -> [n] -> [n] (Remember that length returns a Num), and the expression (:) . length . singleton has type Num => a -> [n] -> [n]. What the resulting expression does is kind of strange: given any value of type a and some list, it will ignore the a and prepend the number 1 to that list.
For simplicity, let's make a function out of that:
constPrependOne :: Num n => a -> [n] -> [n]
constPrependOne = (:) . length . singleton
You should already be familiar with foldr. It performs a right-fold over a list using a function. In this situation, it calls constPrependOne on each element, so the expression foldr constPrependOne [] just constructs a list of ones with equal length to the input list. So let's make a function out of that:
listOfOnesWithSameLength :: Num n => [a] -> [n]
listOfOnesWithSameLength = foldr constPrependOne []
If you have a list [2, 4, 7, 2, 5], you'll get [1, 1, 1, 1, 1] when applying listOfOnesWithSameLength.
Then, the foldr (+) 0 function is another right-fold. It is equivalent to the sum function in Haskell; it sums the elements of a list.
So, let's make a function:
sum :: Num n => [n] -> n
sum = foldr (+) 0
If you now compose the functions:
func = sum . listOfOnesWithSameLength
... you get the resulting expression. Given some list, it creates a list of equal length consisting of only ones, and then sums the elements of that list. It does in other words behave exactly like length, only using a much slower algorithm. So, the final function is:
inefficientLength :: Num n => [a] -> n
inefficientLength = sum . listOfOnesWithSameLength