I am new to Haskell, but I know C. I'm referring Learn You a Haskell for Great Good as study source and currently learning about "List comprehension". Since I can easily make a prime numbers program in C, I tried the same in Haskell with the following code:
primes = [x | x <- [2..100], null [f | f <- [2..round (x/2)], 0 == rem x f]]
--it creates a list of prime numbers upto 100. `f` denotes factors.
--working principle: this code adds those numbers to the main list who have no factors (excluding 1 and the number itself.
But it is showing a big error in my GHCi:
train.hs:84:20:
No instance for (Enum t0)
arising from the arithmetic sequence ‘2 .. 100’
The type variable ‘t0’ is ambiguous
Relevant bindings include primes :: [t0] (bound at train.hs:84:1)
Note: there are several potential instances:
instance forall (k :: BOX) (s :: k). Enum (Data.Proxy.Proxy s)
-- Defined in ‘Data.Proxy’
instance Integral a => Enum (GHC.Real.Ratio a)
-- Defined in ‘GHC.Real’
instance Enum Ordering -- Defined in ‘GHC.Enum’
...plus 8 others
In the expression: [2 .. 100]
In a stmt of a list comprehension: x <- [2 .. 100]
In the expression:
[x |
x <- [2 .. 100],
null [f | f <- [2 .. round (x / 2)], 0 == rem x f]]
train.hs:84:21:
No instance for (Num t0) arising from the literal ‘2’
The type variable ‘t0’ is ambiguous
Relevant bindings include primes :: [t0] (bound at train.hs:84:1)
Note: there are several potential instances:
instance Integral a => Num (GHC.Real.Ratio a)
-- Defined in ‘GHC.Real’
instance Num Integer -- Defined in ‘GHC.Num’
instance Num Double -- Defined in ‘GHC.Float’
...plus three others
In the expression: 2
In the expression: [2 .. 100]
In a stmt of a list comprehension: x <- [2 .. 100]
train.hs:84:49:
No instance for (Integral t0) arising from a use of ‘round’
The type variable ‘t0’ is ambiguous
Relevant bindings include
x :: t0 (bound at train.hs:84:15)
primes :: [t0] (bound at train.hs:84:1)
Note: there are several potential instances:
instance Integral Integer -- Defined in ‘GHC.Real’
instance Integral Int -- Defined in ‘GHC.Real’
instance Integral Word -- Defined in ‘GHC.Real’
In the expression: round (x / 2)
In the expression: [2 .. round (x / 2)]
In a stmt of a list comprehension: f <- [2 .. round (x / 2)]
train.hs:84:57:
No instance for (Fractional t0) arising from a use of ‘/’
The type variable ‘t0’ is ambiguous
Relevant bindings include
x :: t0 (bound at train.hs:84:15)
primes :: [t0] (bound at train.hs:84:1)
Note: there are several potential instances:
instance Integral a => Fractional (GHC.Real.Ratio a)
-- Defined in ‘GHC.Real’
instance Fractional Double -- Defined in ‘GHC.Float’
instance Fractional Float -- Defined in ‘GHC.Float’
In the first argument of ‘round’, namely ‘(x / 2)’
In the expression: round (x / 2)
In the expression: [2 .. round (x / 2)]
train.hs:84:65:
No instance for (Eq t0) arising from a use of ‘==’
The type variable ‘t0’ is ambiguous
Relevant bindings include
f :: t0 (bound at train.hs:84:40)
x :: t0 (bound at train.hs:84:15)
primes :: [t0] (bound at train.hs:84:1)
Note: there are several potential instances:
instance (Eq a, Eq b) => Eq (Either a b)
-- Defined in ‘Data.Either’
instance forall (k :: BOX) (s :: k). Eq (Data.Proxy.Proxy s)
-- Defined in ‘Data.Proxy’
instance (GHC.Arr.Ix i, Eq e) => Eq (GHC.Arr.Array i e)
-- Defined in ‘GHC.Arr’
...plus 28 others
In the expression: 0 == rem x f
In a stmt of a list comprehension: 0 == rem x f
In the first argument of ‘null’, namely
‘[f | f <- [2 .. round (x / 2)], 0 == rem x f]’
Failed, modules loaded: none.
I'm sorry, but I rechecked my code, but it just seems fine, considering the syntax.
However, when I put the same code in my ghci>
, the result is bit different:
Prelude> let primes = [x | x <- [2..100], null [f | f <- [2..round (x/2)], 0 == rem x f]]
Prelude> primes
<interactive>:12:1:
No instance for (Integral t0) arising from a use of ‘it’
The type variable ‘t0’ is ambiguous
Note: there are several potential instances:
instance Integral Integer -- Defined in ‘GHC.Real’
instance Integral Int -- Defined in ‘GHC.Real’
instance Integral Word -- Defined in ‘GHC.Real’
In the first argument of ‘print’, namely ‘it’
In a stmt of an interactive GHCi command: print it
I would be glad if I get to know my mistake.
Same code from my textbook:----------------
primes
as integer list like this:primes :: [Integer]
But why did this problem did not occur for other functions?
Like this function just worked fine. I had not declare listCom
's type:
listCom = [2*x | x <- [1..50], rem x 3 == 0]
fromIntegral
with x/2
:f <- [2..round (fromIntegral x/2)]
Now why I have to state that even if I have already converted x/2
to integer using round
?
Edit:
If there is problem with [2..round (x/2)]
, then does this code work perfectly fine:
ii = 33
samLis = [2..round (ii/2)]
Now why I have to state that even if I have already converted x/2 to integer using round?
It is not converting x/2
, it is converting x
. Indeed, (/) :: Fractional a => a -> a -> a
works with fractional numbers, and an Integer
or any other integral number is not a Fractional
number, so without the fromIntegral
, it requires that x
is both Fractional
(because you use it in x/2
), and Integral
(since you use it in rem :: Integral a => a -> a -> a
), while one can technically "fabricate" such type, it makes no sense: a number type is either integral, or fractional, not both.
If you thus implement this as:
primes = [x | x <- [2 .. 100], null [f | f <- [2 .. round (fromIntegral x / 2)], 0 == rem x f]]
we're done.
The prime check is however far from efficient: we can for example already stop at √n for checking.
But why did this problem did not occur for other functions? Like this function just worked fine. I had not declare
listCom
's type.
Because there it uses type defaulting rules, will use Integer
, and since you don't use x
in any function that forces a type constraint it can not satisfy, there is no problem.