I wrote my first program in Haskell today. It compiles and runs successfully. And since it is not a typical “Hello World” program, it in fact does much more than that, so please congrats me 😀
Anyway, I’ve few doubts regarding my code, and the syntax in Haskell.
Problem:
My program reads an integer N from the standard input and then, for each integer i in the range [1,N], it prints whether i is a prime number or not. Currently it doesn’t check for input error. 🙂
Solution: (also doubts/questions)
To solve the problem, I wrote this function to test primality of an integer:
is_prime :: Integer -> Bool
is_prime n = helper n 2
where
helper :: Integer -> Integer -> Bool
helper n i
| n < 2 * i = True
| mod n i > 0 = helper n (i+1)
| otherwise = False
It works great. But my doubt is that the first line is a result of many hit-and-trials, as what I read in this tutorial didn’t work, and gave this error (I suppose this is an error, though it doesn’t say so):
prime.hs:9:13:
Type constructor `Integer' used as a class
In the type signature for `is_prime':
is_prime :: Integer a => a -> Bool
According to the tutorial (which is a nicely-written tutorial, by the way), the first line should be: (the tutorial says (Integral a) => a -> String, so I thought (Integer a) => a -> Bool should work as well.)
is_prime :: (Integer a) => a -> Bool
which doesn’t work, and gives the above posted error (?).
And why does it not work? What is the difference between this line (which doesn’t work) and the line (which works)?
Also, what is the idiomatic way to loop through 1 to N? I’m not completely satisfied with the loop in my code. Please suggest improvements. Here is my code:
--read_int function
read_int :: IO Integer
read_int = do
line <- getLine
readIO line
--is_prime function
is_prime :: Integer -> Bool
is_prime n = helper n 2
where
helper :: Integer -> Integer -> Bool
helper n i
| n < 2 * i = True
| mod n i > 0 = helper n (i+1)
| otherwise = False
main = do
n <- read_int
dump 1 n
where
dump i x = do
putStrLn ( show (i) ++ " is a prime? " ++ show (is_prime i) )
if i >= x
then putStrLn ("")
else do
dump (i+1) x
You are misreading the tutorial. It would say the type signature should be
These are different types:
Integer -> BoolIntegerand gives back a value of typeBool.Integral a => a -> Boolaand gives back a value of typeBool.a? It can be any type of the caller’s choice that implements theIntegraltype class, such asIntegerorInt.(And the difference between
IntandInteger? The latter can represent an integer of any magnitude, the former wraps around eventually, similar toints in C/Java/etc.)The idiomatic way to loop depends on what your loop does: it will either be a map, a fold, or a filter.
Your loop in
mainis a map, and because you’re doing i/o in your loop, you need to usemapM_.Meanwhile, your loop in
is_primeis a fold (specificallyallin this case):(And on a minor point of style, it’s conventional in Haskell to use names like
isPrimeinstead of names likeis_prime.)