I'm trying to create a function that eliminates multiples of a given Integer from a list of Integers, in the form multiples x [y], where x is the given Integer, and y is the list.
Here's what I have:
multiples :: Integer -> [Integer] -> [Integer]
multiples a [] = []
multiples a [b] = filter (\l -> l `mod` a /= 0) [b]
multiples will fail when called, saying "Non-exhaustive patterns in function multiples". So I used ghci -Wall with my file to see what patterns were missing, and it returns this:
multiples.hs:2:1: warning: [-Wincomplete-patterns]
Pattern match(es) are non-exhaustive
In an equation for `multiples': Patterns not matched: _ (_:_:_)
multiples.hs:2:11: warning: [-Wunused-matches]
Defined but not used: `a'
I get the feeling I'm missing something really simple with line 2, but I'm a bit stuck. What am I doing wrong?
Welcome to Stack Overflow! There are a couple of things to fix in your function, but I'll start with the one you seem the most confused about: here [b] is a pattern matching a one-element list, naming its single item b. ([b, c] would be a pattern matching a two-element list, etc.) It's not a pattern matching an arbitrarily long list of bs. GHC is telling you off because you haven't accounted for the case where the function has been given a two-or-more-element list.
If you want to match an arbitrary list of bs, omit the square brackets. Additionally, the first line of your function is not necessary because the second line already deals with that case.
multiples :: Integer -> [Integer] -> [Integer]
multiples a bs = filter (\b -> b `mod` a /= 0) bs
Or, using a list comprehension,
multiples :: Integer -> [Integer] -> [Integer]
multiples a bs = [b | b <- bs, b `mod` a /= 0]
Two more things: I'd name this function withoutMultiples because it filters out multiples of a, and because Haskell functions are curried by default you can omit the bs in the filter version.
withoutMultiples :: Integer -> [Integer] -> [Integer]
withoutMultiples a = filter (\b -> b `mod` a /= 0)
Your pattern
multiples a [b]
expects an Integer (bound to name "a") and list of Integer containing one element (bound to name "b"). Remove square brackets (which will change type of "b" to [Integer]) in this pattern and it should be working. Also you can curry this function to form
multiples a = filter (\l -> l `mod` a /= 0)
and omit first pattern as it should be covered by filter function.
Related
I am new to Haskell and I'm attempting a task in which the result should be the sum of the last two integers in a string.
I completely understand the overall addition part however it is the manipulation of the string recursively that I'm struggling with. To attempt the task I first 'flipped' the string with the last integer becoming the first for said string to be split after the nth term, in this case 2.
For example, with the given string 1,2,3,4,5,6,7. The result would be 13 as in 6+7=13.
sum' :: [a] -> [a]
sum' = foldl (\acc x -> x : acc) []
sum' :: [a] -> [a]
sum' [] = []
sum' xs = let h = splitAt 1 xs in h
sum' :: (Num a) => [a] -> a
sum' [] = 0
sum' (xs:x) = xs + sum' (x)
main :: IO()
main = do
print(sum'[1,2,3,4,5,6,7])
It is currently very messy and extremely inefficient (not to mention broken). Any help on the functions of haskell which will help me is greatly appreciated.
Working with the ends of lists is hard. My suggestion would be to reverse the list and take 2 elements off the front.
let a:b:_ = reverse [1,2,3,4,5,6,7] in a + b
By the way what you have here is not a String but a List of Int. While Strings are always lists in Haskell, not all Lists are Strings
You should recurse until only two elements are left in the list. So you implement two clauses for the normal behavior, and like some extra ones for the "corner cases".
The base case (1) is a list of two elements in which you need to sum up the elements; the recursive case (2) deals with a list with three or more elements, and recurses on the tail of the list:
sumlast2 :: Num a => [a] -> a
sumlast2 [x1, x2] = … -- (1)
sumlast2 (_:xs#(_:_:_)) = … -- (2)
-- … extra clauses for corner cases …
where you still need to fill in the … parts. In the second clause (2), xs is thus tail of the list: a list with all elements except the first one. You thus will need to define sumlast2 with three or more elements in terms of sumlast2.
I want to shift a list by n elements to the left. Why do I get an error if I want to change the order from (x:xs) to (xs:x)?
shift n list#(x:xs)
| n == 0 = list
| otherwise = shift (n-1) (xs:x) -- (xs:x) error
Occurs check: cannot construct the infinite type: a ~ [a]
I don't know how to interpret this error. Maybe someone of you can help me.
Thank you very much.
EDIT: As it was already mentioned, the correct term to use is rotate and not shift
Why do I get an error if I want to change the order from (x:xs) to (xs:x)?
Because the types do not match. The type of (:) is (:) :: a -> [a] -> [a]. It thus expects an element x (type a) and a list with the rest of the elements (type [a]). You can not just use (:) in the opposite way.
You can use the (++) :: [a] -> [a] -> [a] to concatenate two lists together. We can thus rotate to the left by dropping n elements from the list and concatenating this with the first n elements of the list to this.
rotateL :: Int -> [a] -> [a]
rotateL 0 list = list
rotateL n list | n < 0 = error "Negative index"
| otherwise = drop n list ++ take n list
or we can, like #YannVernier says, use splitAt :: Int -> [a] -> ([a], [a]):
rotateL :: Int -> [a] -> [a]
rotateL 0 list = list
rotateL n list | n < 0 = error "Negative index"
| otherwise = lb ++ la
where (la, lb) = splitAt n list
or without mentioning the list parameter:
rotateL :: Int -> [a] -> [a]
rotateL 0 = id
rotateL n | n < 0 = error "Negative index"
| otherwise= uncurry (flip (++)) . splitAt n
Note: based on how your attempt, I think you actually want to rotate the list to the left, not shift it, since that would mean that you simply drop the first n elements, and fill it perhaps with some extra value.
Note: in case n is larger than the length of the list, then the rotateL will act as an identity function. That might not be the desired behavior. I leave it as an exercise to fix this edge-case.
It's not the names that define the types, but the positions in a function call, or type declarations. If we check the type of :, we see that the second argument is a list:
Prelude> :t (:)
(:) :: a -> [a] -> [a]
So pattern matching on this constructor will always give you the head and tail, not the init and last. Thus, using both x:xs and xs:x, you've declared that a and [a] are the same type, and the compiler balks. You could perform the append using e.g. xs ++ [x].
Data.Sequence has a type that does support both head and last patterns in the operators :<| and |>:.
In general, (singly linked) lists only make the head element efficiently accessible; operations like appending or even checking lengths are costly. When all you need is a stream or stack, they're great, but a long distance reordering operation like the rotation is better handled by a rope or circular buffer type. Either is available in Haskell, in e.g. container's Seq or ring-buffer's RingBuffer. Data.ByteString.Lazy and Data.Text.Lazy are also rope types.
I am trying to learn Haskell by creating some basic functions. The function that I am currently trying to work on is called primeFactors and it needs to return a list of the prime factors for a given number n. Currently I have the following:
factors :: Integral a => a -> [a]
factors n = [x | x <- [1..n], n `mod` x == 0]
isPrime :: Integral a => a -> Bool
isPrime n = factors n == [1, n]
primeFactors :: Integral a => a -> [a]
primeFactors n = []
I figure I should use the first two functions, but I'm not exactly sure how to do so. Functional programming is totally new to me.
In the end if I call it like so: primeFactors 10 I expect it to return [5, 2]
Any help is appreciated. Thanks in advance.
You can use the "filter" function. It has this type:
filter :: (a -> Bool) -> [a] -> [a]
The first argument is the predicate and the second is the list you are filtering. The result is a list containing only those elements for which the predicate returns True. So you can write any of the following:
primeFactors n = filter isPrime (factors n)
primeFactors n = filter isPrime $ factors n
primeFactors = filter isPrime . factors
The first one should be self explanatory. The second uses the "$" operator, which is just function application with a zero precedence. Its often used to get rid of brackets in the trailing expression. The last is in "point-free" style (the term comes from topology: roughly speaking a point is a variable). The "." operator is defined like this:
(f . g) x = f (g x)
If you substitute "filter isPrime" for "f" and "factors" for "g" into that you will see how it works.
I have to make a 2D list [[Int]]. out of a 1D list [Int] in Haskell.
The function should take to args "r" Int indicates the count of rows and a 1D list, which should be sliced into rows with the length of "r".
If length of the list is longer than r*r then the rest of the list should be dropped.
Howerver
If length of the list is shorter than r*r then the missing elements should be inserted in the list as 0.
Example 1:
Input:
r = 2
list = [1,2,3,4,5,6]
Output: [[1,2], [3,4]]
Example 2:
Input:
r = 3
list = [1,2,3,4,5,6]
Output: [[1,2,3], [4,5,6], [0,0,0]]
So my approach is over thre functions as follow:
zeroList :: Int -> [Int] -> [Int]
zeroList r myList = (take (r*r-(length myList)) (0 : zeroList r myList))
processList :: Int -> [Int] -> [[Int]]
processList r myList = (if (length myList < r*r)
then (myList:(zeroList r myList))
else if (length (myList > r*r))
then (reverse (drop r (reverse myList)))
else
myList)
make2DList :: Int -> [Int] -> [[Int]]
make2DList r myList = (if myList == []
then make2DList
else ( ( take r (processList r myList) ):( make2DList r ( drop r (processList r myList) ) )))
The zeroList function works properly but the other two functions don't work. I some compiling error messages:
D:\haskell\task1.hs:6:63:
Couldn't match expected type `[Int]' with actual type `Int'
Expected type: [[Int]]
Actual type: [Int]
In the return type of a call of `zeroList'
In the second argument of `(:)', namely `(zeroList r myList)'
D:\haskell\task1.hs:14:54:
Couldn't match expected type `[[Int]]'
with actual type `Int -> [Int] -> [[Int]]'
In the expression: make2DList
In the expression:
(if myList == [] then
make2DList
else
((take r myList) : (make2DList r (drop r myList))))
In an equation for `make2DList':
make2DList r myList
= (if myList == [] then
make2DList
else
((take r myList) : (make2DList r (drop r myList))))
Failed, modules loaded: none.
Prelude>
I can't comprehend, why it doesn't work although zeroList r myList. returns an ordinary list.
Could anyone help me please?
I have to admit that I don’t comprehend how you are trying to do it. All this if then else is quite unHaskellish. :-) Also, due to Haskell’s lazy evaluation and infinite lists, it is unnecessary to compute the exact number of needed zeroes etc. beforehand.
A rough draft how it could be done instead:
make2DList r l = take r . chunks r $ l ++ zeroes
where
zeroes = [0,0..]
chunks r xs = take r xs : chunks r (drop r xs)
Explanation:
Extend the list by an infinite number of zeroes so we don’t have to worry about padding anymore.
Make a chunks function that splits any list into chunks of the given length.
Apply chunks to the padded list.
Take as many rows as we need.
I can explain both of the compilation errors, and I have a question for you. I'll take the errors in reverse order.
Error at 14:54
First I'll explain how arguments are applied to functions in Haskell.
The function make2DList has type Int -> [Int] -> [[Int]], which is equivalent to Int -> ( [Int] -> [[Int]] ). This means that, if given one argument r (which must be of type Int) it returns a function of type [Int] -> [[Int]]. This returned function, if given an argument myList (which must be of type [Int]) returns a list of type [[Int]].
This means that the code make2DList r myList is equivalent to (make2DList r) myList. In any case, it must return a value of type [[Int]], that is, a list of lists of Ints.
But you have said that, in the event that myList is empty, it should return just make2DList. Unfortunately make2DList is a function of type Int -> [Int] -> [[Int]] and not a list of lists of type [[Int]], hence the compiler error message
Couldn't match expected type `[[Int]]'
with actual type `Int -> [Int] -> [[Int]]'
The fix is to supply some arguments to this call to make2DList. But do not supply an empty list as the second argument, or you will create an infinite loop. Probably what you actually want to do is to return an empty list of lists, written the same way as an empty list of anything: []
Edit: I should perhaps also explain how if ... then ... else works in Haskell. This is not at all like the if/then/else in imperative languages, and is actually just like the ternary operator. That is,
if a then b else c
in Haskell is, as far as I can tell, exactly the same as
a ? b : c
in another language.
Thus, in order for the whole expression (if a then b else c) to be of the right type, both b and c must be of the right type (and a must be boolean, of course). In your case, the whole if/then/else expression should be of type [[Int]] but your b is the expression make2DList (with no arguments), which is of course a function and not a list of lists as it should be.
Error at 6:63
The type of : is given by (:) :: a -> [a] -> [a]. This means that if whatever is on the left of the : has type a (for some a), then whatever is on the right should have type [a].
That is to say, whatever appears to the left of : will become the first element in the resulting list, and whatever is on the right of : will become the rest of the list, which means that the type of the rest of the list must be a list of the type of whatever the first element is.
Your first element is myList, which has type [Int], and what you're trying to use for the rest of the list is (zeroList r myList), which also has type [Int] and is thus only good as a single element.
Possible fixes (which would compile, but may or may not be correct) could include:
enclosing zeroList r myList in square brackets, thus:
myList:[zeroList r myList]
which would always create a list of two elements, each of which would be a list of Ints
concatenating the two lists, thus:
myList ++ (zeroList r myList)
but this would produce the wrong return type, so you'd have to put the result in another list. The following would compile, but is almost certainly not what you want:
[myList ++ (zeroList r myList)]
That r probably wants to be something like r - (length myList) or something too.
Question
I'm having trouble guessing how your functions are supposed to work. What are each of the two functions processList and make2DList supposed to do? I see that they both have the same type, so what is the difference?
import Data.List (replicate)
takeElse :: Int -> a -> [a] -> [a]
takeElse 0 _ _ = []
takeElse n alt [] = replicate n alt
takeElse n alt (x : xs) = x : takeElse (n - 1) alt xs
exotic :: Int -> a -> [a] -> [[a]]
exotic dum alt lst = exot dim lst
where
exot 0 _ = []
exot n xs = takeElse dim alt xs : exot (n - 1) (drop dim xs)
such that
exotic 3 0 [1,2,3,4] == [[1,2,3],[4,0,0],[0,0,0]]
exotic 1 ' ' "Hello" == ["H"]
exotic 4 ' ' "Hello" == ["Hell","o "," "," "]
takeElse 10 ' ' "Hello" == "Hello "
I'm trying to write a program in Haskell
that gets a list (of integer) and prints out the number of elements that are bigger than the list's average
So far I tried
getAVG::[Integer]->Double
getAVG x = (fromIntegral (sum x)) / (fromIntegral (length x))
smallerThanAVG:: [Integer]->Integer
smallerThanAVG x = (map (\y -> (if (getAVG x > y) then 1 else 0)) x)
For some reason I'm getting this error
Couldn't match expected type `Double'
against inferred type `Integer'
Expected type: [Double]
Inferred type: [Integer]
In the second argument of `map', namely `x'
It could be that I haven't written the logic correctly, although I think I did..
Ideas?
These errors are the best kind, because they pinpoint where you have made a type error.
So let's do some manual type inference. Let's consider the expression:
map (\y -> (if (getAvg x > y) then 1 else 0)) x
There are a few constraints we know off the bat:
map :: (a -> b) -> [a] -> [b] -- from definition
(>) :: Num a => a -> a -> Bool -- from definition
getAvg :: [Integer] -> Double -- from type declaration
1, 0 :: Num a => a -- that's how Haskell works
x :: [Integer] -- from type declaration of smallerThanAVG
Now let's look at the larger expressions.
expr1 = getAvg x
expr2 = (expr1 > y)
expr3 = (if expr2 then 1 else 0)
expr4 = (\y -> expr3)
expr5 = map expr4 x
Now let's work backwards. expr5 is the same as the RHS of smallerThanAVG, so that means it has the same result type as what you've declared.
expr5 :: Integer -- wrong
However, this doesn't match our other constraint: the result of map must be [b] for some b. Integer is definitely not a list (although if you get facetious, it could be coerced into a list of bits). You probably meant to sum that list up.
expr6 = sum expr5
sum :: Num a => [a] -> a
Now let's work forwards.
expr1 :: Double -- result type of getAvg
y :: Double -- (>) in expr2 requires both inputs to have the same type
expr4 :: (Integer -> [a]) -- because for `map foo xs` (expr5)
-- where xs :: [a], foo must accept input a
y :: Integer -- y must have the input type of expr4
Herein lies the conflict: y cannot be both a Double and an Integer. I could equivalently restate this as: x cannot be both a [Double] and [Integer], which is what the compiler is saying. So tl;dr, the kicker is that (>) doesn't compare different types of Nums. The meme for this sort of problem is: "needs more fromIntegral".
(getAvg x > fromIntegral y)
Your code has two errors.
Although the type signature in the code declares that smallerThanAVG x evaluates to an Integer, its code is map ... x, which clearly evaluates to a list instead of a single Integer.
In the code getAVG x > y, you are comparing a Double to an Integer. In Haskell, you can only compare two values of the same type. Therefore, you have to use fromIntegral (or fromInteger) to convert an Integer to a Double. (This is essentially what caused the error message in the question, but you have to get used to it to figure it out.)
There are several ways to fix item 1 above, and I will not write them (because doing so would take away all the fun). However, if I am not mistaken, the code you are aiming at seems like counting the number of elements that are smaller than the average, in spite of what you write before the code.
Styling tips:
You have many superfluous parentheses in your code. For example, you do not have to parenthesize the condition in an if expression in Haskell (unlike if statement in C or Java). If you want to enjoy Haskell, you should learn Haskell in a good style instead of the Haskell which just works.
You call the variable which represents a list “x” in your code. It is conventional to use a variable name such as xs to represent a list.
Others have explained the errors beautifully.
I'm still learning Haskell but I'd like to provide an alternative version of this function:
greaterThanAvg :: [Int] -> [Int]
greaterThanAvg xs = filter (>avg) xs
where avg = sum xs `div` length xs
cnt = length $ greaterThanAvg [1,2,3,4,5]