haskellprimestype-declaration

Prime no.s function not working in Haskell


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:----------------

  1. I had to declare 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]
  1. I have to modify the draw list of factors by adding 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)]

Solution

  • 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.