Haskell sum a list with testcase - list

So I have the following code:
data List = Empty | Cons Integer List deriving Show
list = Cons 1 (Cons 7 (Cons 9 (Cons 3 Empty)))
Now I want to sum up the list created from above with this function:
-- sumList
sumList :: List -> Integer
sumList = sum
I do also have a testcase:
testSum = putStrLn ("expected: 20\ncomputed: " ++ show (sumList list))
My problem is, that I get the following error message:
• Couldn't match type ‘List’ with ‘t0 Integer’
Expected type: List -> Integer
Actual type: t0 Integer -> Integer
• In the expression: sum
In an equation for ‘sumList’: sumList = sum

data List = Empty | Cons Integer List deriving Show
sumList :: List -> Integer
sumList Empty = 0
sumList (Cons x xs) = x + sumList xs
As you can see, since List is a recursive data type, meaning it can hold instances of itself, we need to recursively open the members and add them all together.
As a test:
λ> list = Cons 1 (Cons 7 (Cons 9 (Cons 3 Empty)))
λ> sumList list
20
In your code, you are using sum from Data.Foldable. sum has the following signature:
λ> :t sum
sum :: (Foldable t, Num a) => t a -> a
This means that it needs a data type with an instance of the Foldable class to be able to work on, which List obviously does not have.

Related

Haskell: List manipulation

I want to write a function which takes a input list and manipulates it in the following way:
Step 1: Take the first element of the list and the last element of the list and put it together in a sublist.
Step 2: Take the second element of the list and the second last element of the list and put it together in the next sublist.
Step 3: Take the third element of the list and the third last element of the
list and put it together in next sublist.
Continue this according to the same scheme (for a list of n elements)...
If the number of elements of the input list is odd the n/2 element of the input list will be added as last sublist of the output list.
Example:
[1,2,3,4,5,6,7]
-- should be transformed to
[[1,7],[2,6],[3,5],[4]]
I already wrote a function which takes every 2 elements of a list and puts it together in sublists and I am wondering if this code might help me with my problem above:
g2 :: [a] -> [[a]]
g2 [] = []
g2 (x1:x2:xs) = [x1,x2]: g2 xs
g2 xs = [xs]
Here's one that does it in one pass:
pairs :: [a] -> [[a]]
pairs xs = fst (go xs xs) where
go (x:xs) (_:_:ys) = f x (go xs ys)
go (x:xs) [_] = ([[x]],xs)
go xs [] = ([],xs)
f x (xs,y:ys) = ([x,y]:xs,ys)
How does it work? Let's look at the first two arguments of go first, and in particular this line:
go (x:xs) (_:_:ys) = f x (go xs ys)
Those two arguments are both from the same list (xs), but we take 2 items off of one, and only one off of the other. Why? So we know when we hit the halfway point. Look at this function for comparison:
halfway xs = go xs xs
where
go (_:xs) (_:_:ys) = go xs ys
go xs _ = xs
>>> halfway [1..6]
[4,5,6]
Now, once we get to the halfway point we'll need to "zip" it with the other list. But it needs to be in reverse! How do we do this? A handy way to reverse any function in one pass is to first write it as a fold. Here's zip written as a fold:
zip = foldr (\x k (y:ys) -> (x,y) : k ys) (const [])
To "reverse" it, you just apply is as a foldl rather than as a foldr (you also have to flip the closure).
For our uses, we basically build up the base as we go (in the form of k). So no our function looks like this:
pairs :: [a] -> [[a]]
pairs xs = go xs xs (const []) where
go (y:ys) (_:_:zs) k = go ys zs (f y k)
go (y:ys) [_] k = [y] : k ys
go ys [] k = k ys
f x k (y:ys) = [x,y] : k ys -- same `f` as from `zip`
There's still one problem: the list is returned in the wrong order. To fix this, we replace the list with a difference list, and swap the order of the appends.
Finally, we un-CPS the function, and we get the above.
Here's one using transpose
import Data.List
g2 xs =
transpose [take (x + y) xs, take x (reverse xs)]
where (x, y) = (length xs) `divMod` 2
Note that we have to use drop 1 instead of tail here to avoid errors for odd-length lists.
g2 :: [a] -> [[a]]
g2 [] = []
g2 xs = [first xs] ++ (g2 . drop 1 $ init xs)
where first (x:[]) = [x]
first xs = [head xs, last xs]
Two more, the second is using unfoldr:
pair xs = take (length xs `div` 2) $ zip xs (reverse xs)
-- Note: uses tuples instead of lists
import Data.List
pairs2 = unfoldr (\xs ->
if length xs < 2
then Nothing
else Just ([head xs, last xs], init.tail $ xs))
xs = [2,3,4,7,6]
pair xs -- [(2,6),(3,7)]
pair2 xs -- [[2,6],[3,7]]

Couldn't match expected type `[a]' with actual type `a'

I have the following function which should adds up all numbers in a given list up to the current position. For example, subtotal [1, 2, 3, 4] = [1, 3, 6, 10], because 1 = 1, 1 + 2 = 3, 1 + 2 + 3 = 6 and 1 + 2 + 3 + 4 = 10.
Here's my code:
subtotal :: Num a => [a] -> [a]
subtotal [] = []
subtotal xs = [y | n <- [1..length xs], y <- sum(take n xs)]
The problem is Im getting this error:
cw.hs:3:46: error:
* Couldn't match expected type `[a]' with actual type `a'
`a' is a rigid type variable bound by
the type signature for:
subtotal :: forall a. Num a => [a] -> [a]
at cw.hs:1:1-31
* In the expression: sum (take n xs)
In a stmt of a list comprehension: y <- sum (take n xs)
In the expression:
[y | n <- [1 .. length xs], y <- sum (take n xs)]
* Relevant bindings include
xs :: [a] (bound at cw.hs:3:10)
subtotal :: [a] -> [a] (bound at cw.hs:2:1)
|
3 | subtotal xs = [y | n <- [1..length xs], y <- sum(take n xs)]
| ^^
How can I fix it?
sum(take n xs) is not a list, so you can not iterate over it. In order to add the result of an expression to a list you put the expression in the head of the list comprehension:
subtotal :: Num a => [a] -> [a]
subtotal xs = [sum (take n xs) | n <- [1..length xs]]
But you here use length. length is a bit a dangerous function since lists can be infinite, and then your function will simply keep looping, and never return an element. You can use inits however to obtain all the lists:
Prelude Data.List> inits [1,4,2,5]
[[],[1],[1,4],[1,4,2],[1,4,2,5]]
So you can use:
import Data.List(inits)
subtotal :: Num a => [a] -> [a]
subtotal xs = [sum sub | sub <- tail (inits xs)]
But this is still not very effectively: now we calculate the sum of every sublist. But a problem here is that we calculate the sum of every list separately. This is weird since the sum of the i-th result is simply the sum of the i-1-th result plus the i-th element of xs. We can use scanl1 :: (a -> a -> a) -> [a] -> [a]:
subtotal :: Num a => [a] -> [a]
subtotal xs = scanl1 (+) xs
or even more simple and elegant:
subtotal :: Num a => [a] -> [a]
subtotal = scanl1 (+)
In a list comprehension, the statement y <- ys means that ys is a list and y iterates over the elements of that list. So y <- sum (take n xs) means that sum produces a list and you iterate over that list. But sum only produces a single number, not a list; so you get an error.
You want to use let instead of <- to assign simple expressions:
subtotal xs = [y | n <- [1..length xs], let y = sum(take n xs)]
Or just put the expression directly into the head of the comprehension:
subtotal xs = [sum (take n xs) | n <- [1..length xs]]
PS: Your first case (for the empty list) is redundant. It's just a special case of the second.

Filter elements from nested lists

I am having a hard time with understanding the logic behind functional programming. So, this should be something quite easy but not working for me.
What i am trying to do is:
A function with a parameter list, and a list is something like this: [[1,2,3], [5,7,8,12,34], [2,4,6,8]]
and first i should delete the values less than 6 and then delete all the lists with less than 2 elements. My code is like this:
f11 :: [[Int]] -> [[Int]]
f11 xs = ( filter (\s -> if a <= 6 a then True else False )) (map (filter (\x -> length x <= 2)) xs)
You can also use the do notation, thanks to lists' instance of Monad.
f11 xss = do
xs <- xss
let ys = [x | x <- xs, x >= 6]
guard (length ys <= 2)
return ys
do notation for lists basically denotes a foreach loop. We extract each element xs from xss, then feed it through a list comprehension to filter out the elements less than 6, naming the result ys. Then guard filters out ys longer than 2.
You are getting it the other way around, check this:
f11 :: [[Int]] -> [[Int]]
f11 = (filter \x-> length x < 2) . (map (filter \x -> x > 6))
It's a matter of taste, but, for readability, you might want to use intermediates:
f11 :: [[Int]] -> [[Int]]
f11 xs =
let
less6Cleared = map (filter (\x -> x >= 6)) xs
in
filter (\x -> length(x) >= 2) less6Cleared
This says that less6Cleared is the list of lists whose all elements have been cleared of less than 6. You now apply a filter to less6Cleared.
If you want to go crazy with point free style and partial function application...
f11 :: [[Int]] -> [[Int]]
f11 = (filter $ (>= 2) . length) . (map $ filter (>= 6))
... but it might not be clearer, especially to those not used to it.
Also I took your requirements of "less than" to be strict, so values of 6 are not deleted, and list of lengths of 2 are not deleted.

Nested chunksOf in Haskell?

Say I want to do this:
nestedChunksOf [3, 2] [1,1,1,2,2,2,3,3,3,4,4,4] == [[[1,1,1], [2,2,2]], [[3,3,3], [4,4,4]]]
In Python, I can do this
def group(a, *ns):
for n in ns:
a = [a[i:i+n] for i in xrange(0, len(a), n)]
return a
group([1,1,1,2,2,2,3,3,3,4,4,4], 3, 2) == [[[1,1,1],[2,2,2]],[[3,3,3],[4,4,4]]]
But in Haskell, I can't just say
nestedChunksOf :: [Int] -> [a] -> [[a]]
or
nestedChunksOf :: [Int] -> [a] -> [[[a]]]
So how can I achieve the same thing in Haskell?
A function like nestedChunksOf can't be done directly in Haskell, at least not one which operates on normal lists. The depth of the list is part of the type, so you can't have an arbitrary depth specified by a parameter.
But what you can do is nest chunksOf.
If we define chunksOf like this:
chunksOf :: Int -> [a] -> [[a]]
chunksOf _ [] = []
chunksOf n xs = fxs : chunksOf n sxs
where (fxs, sxs) = splitAt n xs
We can then nest it:
Main> :l test.hs
[1 of 1] Compiling Main ( test.hs, interpreted )
Ok, modules loaded: Main.
*Main> chunksOf 3 [1,1,1,2,2,2,3,3,3,4,4,4]
[[1,1,1],[2,2,2],[3,3,3],[4,4,4]]
*Main> chunksOf 2 $ chunksOf 3 [1,1,1,2,2,2,3,3,3,4,4,4]
[[[1,1,1],[2,2,2]],[[3,3,3],[4,4,4]]]
I hope that accomplishes what you wanted!
As stated in the other answers, this can't be done directly as in Haskell you always need to know the type of an expression and thus distinguish between [a], [[a]] etc. However, using polymorphic recursion you can define a data type that allows such arbitrary nesting by wrapping each level in a constructor:
data NestedList a = Value a | Nested (NestedList [a])
deriving (Show)
So just Value is isomorphic to a, Nested (Value ...) is isomorphic to [a], double Nested to [[a]] etc. Then you can implement
chunksOf :: Int -> [a] -> [[a]]
...
nestedChunksOf :: [Int] -> [a] -> NestedList a
nestedChunksOf [] xs = Nested (Value xs)
nestedChunksOf (c:cs) xs = Nested (nestedChunksOf cs $ chunksOf c xs)
And indeed
print $ nestedChunksOf [3, 2] [1,1,1,2,2,2,3,3,3,4,4,4]
outputs
Nested (Nested (Nested (Value [[[1,1,1],[2,2,2]],[[3,3,3],[4,4,4]]])))
It can be done fairly easily with dependent types.
We'd like to express that the length of the [Int] argument determines the type of the result. We need two things for that: a list type with fixed length, and a type-level function which computes the return type from the length:
{-# LANGUAGE DataKinds, GADTs, TypeFamilies #-}
import Data.List.Split
data Nat = Z | S Nat -- natural numbers (zero, successor)
data Vec n a where -- "n" length lists of "a" elements
Nil :: Vec Z a
(:>) :: a -> Vec n a -> Vec (S n) a
infixr 5 :>
type family Iterate n f a where
Iterate Z f a = a
Iterate (S n) f a = f (Iterate n f a)
Iterate n f a applies the type constructor f n times to an argument. For example, Iterate (S (S Z)) [] Int reduces to [[Int]]. nestedChunksOf can be written directly now:
nestedChunksOf :: Vec n Int -> [a] -> Iterate (S n) [] a
nestedChunksOf Nil as = as
nestedChunksOf (n :> ns) as = chunksOf n $ nestedChunksOf ns as
Usage:
> nestedChunksOf (2 :> 3 :> Nil) [1,1,1,2,2,2,3,3,3,4,4,4]
[[[1,1,1],[2,2,2]],[[3,3,3],[4,4,4]]]
This can not be achieved in Haskell through "normal" means because it would require a dependent type - the type of the result depends on the length of the first argument.
Perhaps a tuple solution would be acceptable?
{-# Language TypeFamilies #-}
{-# Language FlexibleInstances #-}
import Data.List.Split
class NestedChunksOf a where
nco :: a -> [b] -> AList a b
type AList a b :: *
instance NestedChunksOf (Int,Int) where
nco (f,s) xs = chunksOf f (chunksOf s xs)
type AList (Int,Int) a = [[[a]]]
-- More instances as desired.

Haskell 99 Problems #7: Prepend vs Append to List

This passes:
data Nested List a = Elem a | List [NestedList a]
flatten :: NestedList a -> [a]
flatten (Elem a) = [a]
flatten (List (x:xs)) = flatten x ++ flatten (List xs)
flatten (List []) = []
This fails:
data NestedList a = Elem a | List [NestedList a]
flatten :: NestedList a -> [a]
flatten (Elem a) = [a]
flatten (List (x:xs)) = flatten x : flatten (List xs)
flatten (List []) = []
Error is:
Couldn't match expected type `a' with actual type `[a]'
`a' is a rigid type variable bound by
the type signature for flatten :: NestedList a -> [a]
at 007.hs:2:12
Relevant bindings include
xs :: [NestedList a] (bound at 007.hs:4:18)
x :: NestedList a (bound at 007.hs:4:16)
flatten :: NestedList a -> [a] (bound at 007.hs:3:1)
In the first argument of `(:)', namely `flatten x'
In the expression: flatten x : flatten (List xs)
The difference is ++ instead of :. I know the former appends, the latter prepends, but why doesn't : work in this case? I don't understand the error.
Actually ++ is the concatenation operator, which expects both the operators to be a list in this particular case. Since flatten returns a list, ++ concatenates them happily.
But, : just prepends only one item to a list. Since flatten x in flatten x : flatten (List xs) returns a list, : throws this error.