Guards and concatiating to lists in an anonymous function - haskell

I am trying to wrap my head around the syntax of Haskell.
This problem is very simple to solve logically. I have to break up a list of positive and negative integers and group them such that
[1,2,3,-1,-2,-3,1,2,3] becomes [[1,2,3],[-1,-2,-3], [1,2,3]]
I would like to use a higher order function, foldr to be able to do that with an anonymous function taking in two arguements.
This is what I have so far.
split = foldr (\ x y -> if (x > 0)
then if (head (head y)) < 0
then [x] : y
else x : head y --error here
else if (x < 0)
then if (head (head y)) > 0
then [x] : y
else x : head y
else y
)
[[]]
this is the error i get
Occurs check: cannot construct the infinite type: a0 = [a0]
In the first argument of `(:)', namely `x'
In the expression: x : head y
In the expression:
if (head (head y)) < 0 then [x] : y else x : head y
I have two questions.
1) Why am I getting a type error at line 7?
Am I not concatenation an integer (x) to a list of integers (head y)
2) How do you write the conditions out using guards? I tried doing it but I kept getting parsing error at '|'

A function can have only one concrete return type and [x] : y is a different type from x : head y.
It's probably easier to write it with takeWhile and dropWhile:
split l = split' (if head l > 0 then (>) else (<)) l
where split' op [] = []
split' op l = takeWhile (`op` 0) l : split (dropWhile (`op` 0) l)

You're simply missing to keep tail y. In
foldr (\ x y -> if (x > 0)
then if (head (head y)) < 0
then [x] : y
else x : head y
you have x :: (Num a, Ord a) => a, y :: (Num a, Ord a) => [[a]], and head y :: (Num a, Ord a) => [a].
So forgetting the tail y shaves off one layer of []. the else branch should be
else (x:head y) : tail y
in both branches of the outer if.
But, your function has two semantic problems after that.
First, you don't treat the case that head y is empty, that will cause an exception when the end of the list is reached, and second, it doesn't work on infinite lists, since the combinator function doesn't construct anything of the result before its second argument is known. If the latter is a problem, you can find a sufficiently lazy combinator function in this answer.

Related

How does fold distinguish x from xs in Haskell?

sum' :: (Num a) => [a] -> a
sum' xs = foldl (\acc x -> acc + x) 0 xs
There is no pattern like x:xs. xs is a list. In the lambda function, how does the expression acc + x knows that x is the element in xs?
There is no pattern like x:xs. xs is a list. In the lambda function, how does the expression acc + x knows that x is the element in xs?
In Haskell - like in many programming languages - the name of a variable does not matter. For Haskell it does not matter if you write xs, or x, or acc, or use another identifier. What matters here is actually the position of the arguments.
The foldl :: (a -> b -> a) -> a -> [b] -> a is a function that takes as input a function with type a -> b -> a, followed by an object of type a, followed by a list of elements of type b, and returns an object of type a.
Semantically the second parameter of the function, will be the elements of the list. If you thus wrote \x acc -> x + acc, acc would be the eleemnts of the list, and x the accumulator.
The reason why this binds is because foldl is implemented like:
foldl f z [] = z
foldl f z (x:xs) = foldl f (f z x) xs
It thus is defined itself in Haskell, and thus binds the function to f, the initial element to z, and performs recursion to eventually obtain the result by making a recurslive call where we take the tail of the list, and use (f z x) as new initial value until the list is exhausted.
You can write the sum more elegant as:
sum' :: Num n => [n] -> n
sum' = foldl (+) 0
so here there are no explicit variables in use at all.
It doesn't "know" anything like that - there's no magic going on here.
The definition of foldl is equivalent to:
foldl f acc (x:xs) = foldl f (f acc x) xs
foldl _ acc [] = acc
So going through a simple example using your sum' function:
We start with
sum' [1,2,3]
substituting the definition of sum' we get
foldl (\acc x -> acc + x) 0 [1,2,3]
substituting the definition of foldl (first case):
foldl (\acc x -> acc + x) ((\acc x -> acc + x) 0 1) [2,3]
evaluation the function application of your lambda, we get
foldl (\acc x -> acc + x) (0 + 1) [2,3]
substituting foldl again...
foldl (\acc x -> acc + x) ((\acc x -> acc + x) (0+1) 2) [3]
and evaluating the accumulator:
foldl (\acc x -> acc + x) ((0 + 1) + 2) [3]
and substituting foldl again...
foldl (\acc x -> acc + x) ((\acc x -> acc + x) ((0 + 1) + 2) 3) []
again, evaluating the accumulator:
foldl (\acc x -> acc + x) (((0 + 1) + 2) + 3) []
now we get to the second (terminating) case of foldl because we apply it to an empty list and are left with only:
(((0 + 1) + 2 ) + 3)
which we can of course evaluate to get 6.
As you can see, there's no magic involved here: x is just a name you gave to a function argument. You could've named it user8314628 instead and it would've worked the same way. What's binding the value of the head of the list to that argument isn't any pattern matching you do yourself, but what foldl actually does with the list.
Note that you can evaluate any haskell expression using this step-by-step process; You usually won't have to, but it's useful to do this a couple of times with functions that do more-or-less complicated things and you are unfamiliar with.
how does the expression acc + x knows that x is the element in xs?
It doesn't. It computes a sum of whatever is passed to it.
Note that (\acc x -> acc + x) can be written simply as (+).
Folds take each consecutive values of the input list while making passing the remainder back to a function transparent. If you were to write your own sum’ function, you would have to pass the remainder back to your function. You would also have to pass an accumulator back to your own function to keep a running total. Fold does not make explicit the processing of a list by taking the first value and passing the remainder. What it does explicate is the accumulator. It does also have to keep a running total in the case of a sum function. The accumulator is explicit because some recursive functions may do different things with it.

Maybe Int type error [duplicate]

This question already has answers here:
Operating on a return from a Maybe that contains "Just"
(2 answers)
Closed 5 years ago.
I'm getting a type error because I'm trying to recursively add a Maybe int int the function rankP seen bellow. Because the return type of rankP is Maybe Int, and the type of rankC is a tuple of Ints, it is telling me I cannot add Int with Maybe Int.
type Prog = [Cmd]
data Cmd = LD Int
| ADD
| MULT
| DUP
| INC
| SWAP
| POP Int
deriving Show
type Stack = [Int]
type D = Stack -> Maybe Stack
type Rank = Int
type CmdRank = (Int,Int)
rankC :: Cmd -> CmdRank
rankC (LD _) = (0,1)
rankC ADD = (2,1)
rankC MULT = (2,1)
rankC DUP = (1,2)
rankC INC = (1,1)
rankC SWAP = (2,2)
rankC (POP x) = (x,0)
rankP :: Prog -> Maybe Rank
rankP [] = Nothing
rankP [x] = Just (snd(rankC x) - fst(rankC x))
rankP (x:xs) = if ((Just (snd(rankC x) - fst(rankC x)) + rankP xs) < 0) then Nothing
else Just (snd(rankC x) - fst(rankC x)) + (rankP xs)
Here is the error I am receiving:
hw3.hs:43:64:
Couldn't match expected type `Int' with actual type `Maybe Rank'
In the return type of a call of `rankP'
In the first argument of `Just', namely `(rankP xs)'
In the second argument of `(+)', namely `Just (rankP xs)'
Failed, modules loaded: none.
I'm getting a slightly different error:
No instance for (Num (Maybe Int)) arising from a use of ‘+’
In the first argument of ‘(<)’, namely
‘(Just (snd (rankC x) - fst (rankC x)) + rankP xs)’
In the expression:
((Just (snd (rankC x) - fst (rankC x)) + rankP xs) < 0)
In the expression:
if ((Just (snd (rankC x) - fst (rankC x)) + rankP xs) < 0) then
Nothing
else
Just (snd (rankC x) - fst (rankC x)) + (rankP xs)
However, note that in
(Just (snd(rankC x) - fst(rankC x)) + rankP xs) < 0
you're trying to use + on two Maybe Rank objects, and compare the result with < to 0. Neither of these can work.
From your code, it looks like you're trying to "extract" the value of a Maybe Rank; see this question about that.
The problem is that you are attempting to do arithmetic with a Maybe Rank when you really need to extract the Rank from the Maybe Rank before doing any math. One way to do this is directly by hand:
rankP (x:xs) = if y == Nothing
then Nothing
else let Just y' = y in
if snd(rankC x) - fst(rankC x) + y' < 0
then Nothing
else Just (snd(rankC x) - fst(rankC x) + y')
where y = rankP xs
There are certainly more elegant ways to do this when you begin to understand the monadic properties of Maybe. I'm not there yet myself to give much help along those lines.

Function elem is throwing errors

My Haskell code is as follows
isNotPrime x = elem 0 map (mod x)[3.. (x-1)]
When compiled it shows these errors
Couldn't match expected type ‘(t1 -> t1) -> [t1] -> t’
with actual type ‘Bool’
The function ‘elem’ is applied to four arguments,
but its type ‘([a0] -> [b0])
-> ((a0 -> b0) -> [a0] -> [b0]) -> Bool’
has only two
In the expression: elem 0 map (mod x) [3 .. (x - 1)]
In an equation for ‘prime’:
prime x = elem 0 map (mod x) [3 .. (x - 1)]
My understanding is that elem accepts two arguments, I do not understand how am I passing 4 arguments in the above code as the map function should just return a list.
You are passing four arguments to the elem function. Function application always associates left, so the expression
f a b c d
is parsed like this:
((((f a) b) c) d)
Therefore, your example is getting parsed like this:
((((elem 0) map) (mod x)) [3.. (x-1)])
That is, elem is being “applied to four arguments”, but of course all Haskell functions are actually just functions of one argument, just curried. What you actually want is a different grouping, so you just need to add some parentheses:
elem 0 (map (mod x) [3.. (x-1)])
Alternatively, you could use $ to avoid writing the parentheses:
elem 0 $ map (mod x) [3.. (x-1)]
Or you could write elem infix, which is a common idiom in Haskell. Like $, this will also change the precedence to be what you want:
0 `elem` map (mod x) [3.. (x-1)]
The four arguments you are passing are 0, map, mod x and [3.. (x-1)]. You intended to pass mod x and [3.. (x-1)] as arguments to map and then pass the result as the second argument to elem, but there's no way for Haskell to know that without parentheses or $. So to make your code work add them:
isNotPrime x = elem 0 (map (mod x) [3.. (x-1)])
-- or
isNotPrime x = elem 0 $ map (mod x) [3.. (x-1)]
Or you can use infix notation, in which case precedence rules (prefix function application binds tighter than any infix operator) removes the need for parentheses:
isNotPrime x = 0 `elem` map (mod x) [3.. (x-1)]

Having trouble with H-15

I am doing Problem 15. Which states:
(**) Replicate the elements of a list a given number of times.
Example:
* (repli '(a b c) 3)
(A A A B B B C C C)
Example in Haskell:
> repli "abc" 3
"aaabbbccc"
My plan was to do something like this:
repli :: [a] -> Integer -> [a]
repli [] y = []
repli (x:xs) y | appendNo x y == [] = repli(xs) y
| otherwise = appendNo x y : (x:xs)
where
appendNo :: a -> Integer -> [a]
appendNo a 0 = []
appendNo a y = a:appendNo a (y-1)
Where I would make a function called appendNo that returns a list of 1 element y times then append it to the original list. Then take the body of the list and repeat this process until there are no more body elements left. But, I get the error:
H15.hs:6:30:
Couldn't match type `a' with `[a]'
`a' is a rigid type variable bound by
the type signature for repli :: [a] -> Integer -> [a] at H15.hs:3:1
In the return type of a call of `appendNo'
In the first argument of `(:)', namely `appendNo x y'
In the expression: appendNo x y : (x : xs)
Failed, modules loaded: none.
6:30 is at the on the p in appendNo in this line:
| otherwise = appendNo x y : (x:xs)
Ok thanks dave4420 I was able to figure it out by doing:
repli :: [a] -> Integer -> [a]
repli [] y = []
repli (x:xs) y = appendNo x y ++ repli(xs) y
where
appendNo :: a -> Integer -> [a]
appendNo a 0 = []
appendNo a y = a:appendNo a (y-1)
| otherwise = appendNo x y : (x:xs)
There is a type error in this line. So ask yourself:
What is the type of appendNo x y?
What is the type of (x:xs)?
What is the type of (:)?
Then you should be able to see why they don't match up.
If you still can't see why they don't match up, ask yourself
What is the type of x?
What is the type of xs?
What is the type of (:)?
Bear in mind that this time the types do match up.
As the problem is solved, let me give you a hint: You should try to think in transformations, not in "loops". Start with some concrete values like n = 3 and list = "ABCD". Then you should think along the lines "I need every element three times". There is already a function for doing the replication, which is surprisingly called replicate. So the sentence can be translated to map (replicate 3) "ABCD", which gives you ["AAA","BBB","CCC","DDD"]. That's almost what you want, you just need to concat the elements. This gives:
repli list n = concat (map (replicate n) list)
Because this operation is very common, there is a concatMap function combining concat and map, as well as the operator (>>=) doing the same, just with flipped arguments. So a very short solution would be:
repli list n = list >>= replicate n
This can be translated to the do-notation or a list comprehension as well:
repli list n = do
x <- list
y <- replicate n x
return y
repli list n = [y | x <- list, y <- replicate n x]

Haskell's if statement for error checking

I wrote a function for the Haar wavelet transformation given that the input is a List with a power of 2. I was trying to error check by making sure that the length of the List is a power of 2 before preforming the transformation. I am comparing the log base 2 of the length of the list to see if it comes out evenly (nothing to the right of the decimal point). I think there is something going on with the if statement in haskell that I am not used to in other languages. It works perfectly if I don't error check and just call haar with the proper argument.
haar :: (Fractional a) => [a] -> [a]
haar xs = if logBase 2 (fromIntegral (length xs)) /= truncate (logBase 2 (fromIntegral (length xs)))
then error "The List must be a power of 2"
else haarHelper xs (logBase 2 (fromIntegral (length xs)))
haarHelper xs 1 = haarAvgs xs ++ haarDiffs xs
haarHelper xs level = haarHelper (haarAvgs xs ++ haarDiffs xs) (level - 1)
haarAvgs [] = []
haarAvgs (x:y:xs) = ((x + y) / 2.0) : haarAvgs xs
haarDiffs [] = []
haarDiffs (x:y:xs) = ((x - y) / 2.0) : haarDiffs xs
I am getting the following error message:
functions.hs:52:13:
Ambiguous type variable `t' in the constraints:
`Floating t'
arising from a use of `logBase' at functions.hs:52:13-48
`Integral t'
arising from a use of `truncate' at functions.hs:52:53-99
Probable fix: add a type signature that fixes these type variable(s)
Failed, modules loaded: none.
There's a much simpler and faster implementation to check that a positive integer is a power of two:
import Data.Bits
powerOfTwo' n = n .&. (n-1) == 0
(Note: this omits the check that n is positive, assuming we can rely on it coming from length.)
Explanation, for the curious:
This algorithm relies on the unique property that only powers of 2 have a single 1 bit (by definition), and decrementing them inverts all the lower bits:
2^n = 100000...
2^n - 1 = 011111...
This leaves no bits in common, making their bitwise-and zero.
For all non-powers-of-two, the decrement will leave at least the highest 1 bit unchanged, keeping the bitwise-and result non-zero.
(Wikipedia: Fast algorithm to check if a positive number is a power of two)
haar :: (Fractional a) => [a] -> [a]
haar xs | r /= (truncate r) = error "The List must be a power of 2"
| otherwise = haarHelper xs (logBase 2 (fromIntegral (length xs)))
where r = logBase 2 (fromIntegral (length xs))
Yea, seems like its something with truncate. Easier way to write if then statements with haskell is shown above. Might help with the debugging a bit.
I think i may know. I think truncate is returning an int where the other number is a float.
Try this
haar :: (Fractional a) => [a] -> [a]
haar xs | r /= w = error "The List must be a power of 2"
| otherwise = haarHelper xs (logBase 2 (fromIntegral (length xs)))
where
r = logBase 2 (fromIntegral (length xs))
w = intToFloat (truncate r)
haarHelper xs 1 = haarAvgs xs ++ haarDiffs xs
haarHelper xs level = haarHelper (haarAvgs xs ++ haarDiffs xs) (level - 1)
haarAvgs [] = []
haarAvgs (x:y:xs) = ((x + y) / 2.0) : haarAvgs xs
haarDiffs [] = []
haarDiffs (x:y:xs) = ((x - y) / 2.0) : haarDiffs xs
intToFloat :: Int -> Float
intToFloat n = fromInteger (toInteger n)
To complement Matt's answer:
haar :: (Fractional a) => [a] -> [a]
haar xs | r /= (fromIntegral $ truncate r) = error "The List must be a power of 2"
| otherwise = haarHelper xs r
where r = logBase 2 (fromIntegral (length xs))
Convert the Integral result of truncate using fromIntegral
You can use the definition of r in haarHelper xs r
Here's a version of haar that I'll argue is a little nicer:
haar :: (Fractional a) => [a] -> [a]
haar xs = maybe (error "The List must be a power of 2")
(haarHelper xs)
(intLogBase 2 $ length xs)
intLogBase :: (Integral a) => a -> a -> Maybe Int
intLogBase b n = intLogBase' b 1 n
where
intLogBase' b p 1 = Just p
intLogBase' b p n
| r /= 0 = Nothing
| otherwise = intLogBase' b (p + 1) q
where (q, r) = quotRem n b
intBaseLog is a variation of baseLog that works for integers and returns Nothing if the given number isn't a power of the given base. Otherwise it returns the power wrapped in a Just. Unlike with logBase and truncate there's no conversion to floating point numbers: we've got integers all the way through.
The maybe function in Haar takes three arguments. It will evaluate its last argument, and if it's a Nothing it will return the first argument (in this case the error). If the last argument evaluates to a Just, it applies the second argument to the thing inside the Just and returns that.
The problem here is unrelated to the if expression. As mentioned in other answers, it is in your condition where you compare "logBase (...)" to "truncate (logBase (...))". One returns a Floating type, the other returns an Integral type. There are no types (in the standard libraries) that implement both classes, so that condition can't be well-typed as-is.
A pattern I use occasionally when working with powers of two is to keep a list of powers of two and just check whether the number is in that list. For example:
powersOfTwo :: [Integer]
powersOfTwo = iterate (*2) 1
isPowerOfTwo x = xInt == head (dropWhile (<xInt) powersOfTwo)
where xInt = toInteger x
I haven't tested, but my gut tells me that for most purposes this is probably faster than "logBase 2". Even if not, it's more appropriate because it doesn't involve any floating-point math. In particular, your current approach isn't going to work even with the types fixed: truncate (logBase 2 512) == truncate (logBase 2 550) (Edit: although I think I probably misunderstood your intent when I wrote this at first, i realize now that you probably meant to check whether logBase 2 (...) is an exact integer value by comparing the truncated version to a non-truncated version, not by comparing to any known value).

Resources