I am a really big noob to Haskell.
I have this code:
4 sieve n i = if i < n
5 then
6 do {
7 innerSieve n;
8 sieve n (i + 1);
9 }
10 else -1
11
12 innerSieve n = return n
13
14 --innerSieve n i j = [x | x <- [i..n], x `mod` j == 0]
and I have this error:
[1 of 1] Compiling Main ( sieve.hs, interpreted )
Ok, modules loaded: Main.
*Main> sieve 10 2
<interactive>:1:1:
No instance for (Num (m0 b0))
arising from a use of `sieve'
Possible fix: add an instance declaration for (Num (m0 b0))
In the expression: sieve 10 2
In an equation for `it': it = sieve 10 2
*Main>
I've been banging my head against a wall trying to understand what it means by "No instance for (Num (m0 b0))." What in the world is a m0 b0?
I thought this might help:
*Main> :t sieve
sieve :: (Ord a, Num a, Num (m b), Monad m) => a -> a -> m b
*Main>
EDIT: I am trying to recreate the sieve of erastothenes by making a recursive function with a list comprehension, basically. I also want to -understand- everything in the code.
Your inner do block has a monadic type. This makes the entire result of sieve have a monadic type of (Monad m) => m b. The else branch of your if statement returns -1, so we know it also has a numeric type. This makes the result of your function (Num (m b), Monad m) => m b. This is very clearly wrong.
I can't figure out what your function is trying to accomplish, so I'm not sure where exactly you went wrong. I would recommend writing explicit type annotations on your functions, to express exactly what you're expecting each function to do. That will, at a minimum, give you better error messages, because instead of saying that the inferred type doesn't make sense, it can point you to exactly what expression doesn't match the explicit type.
BTW, you might find the if statement is better expressed as
sieve n i
| i < n = -- contents of the then block
| otherwise = -1
Haskell is a functional language. This especially means, that you don't tell the compiler Do A then do B but rather calculate A – You don't tell the compiler in what order to do things, rather you tell it what you want to know. You can think of that as having only one (return) statement. Thus, you need to rewrite your code to fit to this paradigma.
The do statement is for a special construct called monad that essentially allows stateful actions (such as printing to the screen) in a consistent manners. You don't need it.
As the others already showed you, you can do something like this. The pipe (|) is called pattern guard and essentially works like an If-then-else:
sieve n i | i < n = --result if condition is met
| otherwise = -1
Remember that you can't change the values of variables. You may need to rewrite your innerSieve to return something.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With