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.
Related
I am trying to write numerical methods for calculating the integral
module NumericalMethods(
trapezoidal_method
) where
type Func = Double -> Double
type Interval = [Double]
type N = Integer
trapezoidal_method:: Func -> Interval -> N -> Double
trapezoidal_method f interval n = h*((f (head interval) + f $ tail interval)/2 + sum_fxs)
where
h :: Double
h = (tail interval - head interval) / fromIntegral n
sum_fxs = sum fxs
fxs = map f [head interval + h * fromIntegral x | x <- [1..n-1]]
I get this error:
• Couldn't match expected type ‘Double -> Double’ with actual type ‘Double’
• Possible cause: ‘f’ is applied to too many arguments
In the first argument of ‘(+)’, namely ‘f (head interval)’
In the first argument of ‘($)’, namely ‘f (head interval) + f’
In the first argument of ‘(/)’, namely ‘(f (head interval) + f $ tail interval)’
|
10 | trapezoidal_method f interval n = h*((f (head interval) + f $ tail interval)/2 + sum_fxs)
| ^^^^^^^^^^^^^^^^^
One issue is your use of $ in f (head interval) + f $ tail interval.
The $ operator has the lowest precedence of almost everything, so it will be interpreted as (f (head interval) + f) $ (tail interval). It is trying to figure out what you mean with f (head interval) + f.
You probably just want to use parentheses: f (head interval) + f (tail interval).
A second issue is your use of lists for intervals. I think tuples would be more suitable:
type Interval = (Double, Double)
Then you can use fst and snd instead of the erroneous head and tail:
trapezoidal_method:: Func -> Interval -> N -> Double
trapezoidal_method f interval n = h*((f (fst interval) + f (snd interval))/2 + sum_fxs)
where
h :: Double
h = (snd interval - fst interval) / fromIntegral n
sum_fxs = sum fxs
fxs = map f [fst interval + h * fromIntegral x | x <- [1..n-1]]
I'm trying to implement the luhn algorithm using the following code:
luhn :: Int -> Bool
luhn x = (tail $ show (foldl (\acc x -> acc + (read x :: Int)) 0 (foldr doEncrypt [] $ zip [0..] (show x)))) == "0"
where
doEncrypt (i,y) acc = if not(even i)
then head(((uncurry (+) . (`divMod` 10) . (*2)) y)) : acc
else (head y) : acc
I now got stuck with the following error:
• Non type-variable argument in the constraint: Integral [a2]
(Use FlexibleContexts to permit this)
• When checking the inferred type
doEncrypt :: forall a1 a2.
(Integral a1, Integral [a2]) =>
(a1, [a2]) -> [a2] -> [a2]
In an equation for ‘luhn’:
luhn x
= (tail
$ show
(foldl
(\ acc x -> acc + (read x :: Int))
0
(foldr doEncrypt [] $ zip [0 .. ] (show x))))
== "0"
where
doEncrypt (i, y) acc
= if not (even i) then
head (((uncurry (+) . (`divMod` 10) . (* 2)) y)) : acc
else
(head y) : acc
I see that the error suggests that the second part of the tuple (a2) is a "Non type-variable argument". However, Haskell seems to identify this a2 argument as an Integral while in fact it is a Char. How can I tell Haskell that this is a Char and that Haskell shouldn't worry any further about this variable's type? Or is there something else I'm not understanding which causes this error?
Edit:
When I remove the (head y) and replace it by y I get instead the following error:
• Couldn't match type ‘Char’ with ‘[Char]’
Expected type: [String]
Actual type: [Char]
• In the third argument of ‘foldl’, namely
‘(foldr doEncrypt [] $ zip [0 .. ] (show x))’
In the first argument of ‘show’, namely
‘(foldl
(\ acc x -> acc + (read x :: Int))
0
(foldr doEncrypt [] $ zip [0 .. ] (show x)))’
In the second argument of ‘($)’, namely
‘show
(foldl
(\ acc x -> acc + (read x :: Int))
0
(foldr doEncrypt [] $ zip [0 .. ] (show x)))’
There where multiple things wrong with my solution, but finally the following code works!
luhn :: Int -> Bool
luhn x = (tail $ show (foldl (\acc x -> acc + (digitToInt x)) 0 (foldr doEncrypt [] $ zip [0..] (show x)))) == "0"
where
doEncrypt (i,y) acc = if not(even i)
then (head $ show(((uncurry (+) . (`divMod` 10) . (*2)) (digitToInt y)))) : acc
else y : acc
Thanks a lot to #WillemVanOnsem for your pointers, without I probably wouldn't have solved this!
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.
I was trying to solve the maximal subsequence sum problem and came up with a neato solution
msss :: (Ord a, Num a) => [a] -> a
msss = f 0 0
f gmax _ [] = gmax
f gmax lmax (x:xs) =
let g = max (lmax + x)
in f (g gmax) (g 0) xs
You call the wrapper function msss, which then calls f, which in turn actually does the work.
The solution is good and afaik working correctly. If for some reason I had to solve the maximal subsequence sum problem in production code, that is how I would do it.
However that wrapper function really bugs me. I love it how in haskell, if you are persistent enough you can write your entire program on a single line, to truly drive home the point that a program is pretty much just one big expression. So I figured I'd try and eliminate the wrapper function for the extra challenge.
It's now I run into the classic problem: How to do anonymous recursion? How do you do recursion when you can't give names to functions? Thankfully the fathers of computing solved this problem ages ago by discovering Fixed-Point Combinators, with the most popular being the Y Combinator.
I've made various attempts to get a Y combinator set up, but they can't get past the compiler.
msss' :: [Int] -> Int
msss' = (\y f x -> f (y y f) x)
(\y f x -> f (y y f) x)
(\g' gmax lmax list -> if list == []
then gmax
else g' (max gmax lmax + head list)
(max 0 lmax + head list)
tail list)
just gives
Prelude> :l C:\maxsubseq.hs
[1 of 1] Compiling Main ( C:\maxsubseq.hs, interpreted )
C:\maxsubseq.hs:10:29:
Occurs check: cannot construct the infinite type:
t0 = t0 -> (([Int] -> Int) -> [Int] -> Int) -> [Int] -> Int
In the first argument of `y', namely `y'
In the first argument of `f', namely `(y y f)'
In the expression: f (y y f) x
C:\maxsubseq.hs:11:29:
Occurs check: cannot construct the infinite type:
t0 = t0 -> (([Int] -> Int) -> [Int] -> Int) -> [Int] -> Int
In the first argument of `y', namely `y'
In the first argument of `f', namely `(y y f)'
In the expression: f (y y f) x
C:\maxsubseq.hs:12:14:
The lambda expression `\ g' gmax lmax list -> ...'
has four arguments,
but its type `([Int] -> Int) -> [Int] -> Int' has only two
In the second argument of `\ y f x -> f (y y f) x', namely
`(\ g' gmax lmax list
-> if list == [] then
gmax
else
g' (max gmax lmax + head list) (max 0 lmax + head list) tail list)'
In the expression:
(\ y f x -> f (y y f) x)
(\ y f x -> f (y y f) x)
(\ g' gmax lmax list
-> if list == [] then
gmax
else
g' (max gmax lmax + head list) (max 0 lmax + head list) tail list)
In an equation for `msss'':
msss'
= (\ y f x -> f (y y f) x)
(\ y f x -> f (y y f) x)
(\ g' gmax lmax list
-> if list == [] then
gmax
else
g' (max gmax lmax + head list) (max 0 lmax + head list) tail list)
Failed, modules loaded: none.
Changing from f (y y f) to f (y f) just gives
C:\maxsubseq.hs:11:29:
Couldn't match expected type `[Int] -> Int'
with actual type `[Int]'
Expected type: (([Int] -> Int) -> t1 -> t0) -> t2 -> t0
Actual type: ([Int] -> Int) -> t1 -> t0
In the first argument of `y', namely `f'
In the first argument of `f', namely `(y f)'
Failed, modules loaded: none.
I've tried taking a different approach by just defining the combinator externally, however this still isn't working and doesn't really meet my challenge to do it in one expression.
y f = f (y f)
msss' :: [Int] -> Int
msss' = y (\g' gmax lmax list -> if list == []
then gmax
else g' (max gmax lmax + head list)
(max 0 lmax + head list)
tail list)
Can you spot what's wrong with what I'm doing? I'm at a loss. The complaining about constructing infinite types really ticks me off because I though Haskell was all about that sort of thing. It has infinite data structures, so why the problem with infinite types? I suspect it has something to do with that paradox which showed untyped lambda calculus is inconsistent. I'm not sure though. Would be good if someone could clarify.
Also, I'm under the impression that recursion can always be represented with the fold functions. Can anyone show me how I could do it by just using a fold? The requirement that the code be a single expression still stands though.
You cannot define the Y combinator like that in Haskell. As you noticed, that results in an infinite type. Fortunately, it is already available in Data.Function as fix, where it's defined using a let binding:
fix f = let x = f x in x
Because the Y combinator needs infinite types, you'll need workarounds like this one.
But I'd write your msss function as a one-liner like this:
msss = fst . foldr (\x (gmax, lmax) -> let g = max (lmax + x) in (g gmax, g 0)) (0, 0)
Well let's think about it for a minute. What type does this lambda expression have?
(\y f x -> f (y y f) x)
Well f is a function (a -> b) -> a -> b, and x is some value b. What does that make y? Well given what we just said about f,
(y y f) :: (a -> b)
Also, since we are applying this expression to itself, we know that y has the same type as the entire expression. This is the part where I get a little bit stumped.
So y is some magical higher-order function. And it takes two functions as input. So it's sort of like y :: f1 -> f2 -> f3. f2 has the form of f, and f3 has the result type mentioned above.
y :: f1 -> ((a -> b) -> a -> b) -> (a -> b)
The question is...what is f1? Well, it has to be the same as the type of y. Do you see how this is getting beyond the power of Haskell's type system? The type is defined in terms of itself.
f1 = f1 -> ((a -> b) -> a -> b) -> (a -> b)
If you want a self-contained "one-liner", then take hammar's suggestion instead:
msss' = (\f -> let x = f x in x)
(\g' gmax lmax list -> case list of
[] -> gmax
(x:xs) -> g' (max gmax lmax + x) (max 0 lmax + x) xs
) 0 0
Although imho if max is allowable, then fix from Data.Function should be allowable as well. Unless you are in some Prelude-only contest.
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).