monalisa
monalisa

Reputation: 19

type issue with n choose k in haskell

I defined this in Haskell

import Math.Combinatorics.Exact.Binomial 
hello i j p n = [(n `choose` l)*(p^l)*((1-p)^(n-l)) | l <- [i,i+1..j]]

It compiles but when I try to run 'hello' with a non integer p, ghci says:

No instance for (Fractional b0) arising from the literal `0.75'
The type variable `b0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Note: there are several potential instances:
  instance Fractional Double -- Defined in `GHC.Float'
  instance Fractional Float -- Defined in `GHC.Float'
  instance Integral a => Fractional (GHC.Real.Ratio a)
    -- Defined in `GHC.Real'
In the third argument of `hello', namely `0.75'
In the expression: hello 2 5 0.75 10
In an equation for `it': it = hello 2 5 0.75 10

Seems like it is a type issue but I am unable to resolve it. Any help is appreciated :)

Upvotes: 0

Views: 302

Answers (2)

ErikR
ErikR

Reputation: 52039

As @JB. pointed out, if you ask ghc (or ghci) for the type of hello it responds with:

hello :: Integral b => b -> b -> b -> b -> [b]

which says that p must be an integral value.

There is a further problem, though. Suppose p is a Double and the rest or the arguments are Int values. Then we have the following types:

  • choose n l is an Int
  • p ^ l is a Double
  • (1-p) ^ (n-l) is a Double

and we are trying to multiple them all together. In Haskell you can't multiply an Int and a Doulble without converting one to the other's type. The way in Haskell to generically convert a integral value is to use fromIntegral, so you want to use:

(fromIntegral (choose n l)) * (p^l) * ((1-p) ^ (n-l))

Upvotes: 0

JB.
JB.

Reputation: 42124

It's a type issue deeper than can be solved:

λ> :t hello
hello :: Integral b => b -> b -> b -> b -> [b]

Your hello function only works on integrals. This is inherited from the choose function, which also only works on integrals:

λ> :t choose
choose :: Integral a => a -> a -> a

Upvotes: 1

Related Questions