I am a Haskell beginner and I am having some trouble understanding this. I have 2 functions defined in a file like this:
expr n x = (x ^ n)/(fact n)
fact n
| n == 0 = 1
| otherwise = n * fact (n - 1)
But when I try to run say expr 3 2
, I keep getting an error like this:
*Main> expr 3 2
<interactive>:31:1: error:
• Ambiguous type variable ‘a0’ arising from a use of ‘print’
prevents the constraint ‘(Show a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance Show Ordering -- Defined in ‘GHC.Show’
instance Show Integer -- Defined in ‘GHC.Show’
instance Show a => Show (Maybe a) -- Defined in ‘GHC.Show’
...plus 22 others
...plus 19 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In a stmt of an interactive GHCi command: print it
I checked the types for the various expressions and I see this:
*Main> :t (/)
(/) :: Fractional a => a -> a -> a
*Main> :t (^)
(^) :: (Integral b, Num a) => a -> b -> a
*Main> :t 3 ^ 6
3 ^ 6 :: Num a => a
*Main> :t fact
fact :: (Eq p, Num p) => p -> p
*Main> :t fact 3
fact 3 :: (Eq p, Num p) => p
*Main> :t 9 / 6
9 / 6 :: Fractional a => a
But I cannot figure out what types to give my functions to avoid this. I tried giving my fact function a type like this since (/) expects Fractional:
fact :: (Fractional a) => Int -> a
But if I try giving my function types, the file doesn't even load in ghci. I can post the error message I get from attempting to load my file with types if that helps.
If I try to add type to the show used when evaluating the expression, that doesn't work either:
*Main> expr 3 2 :: String
<interactive>:37:1: error:
• No instance for (Fractional String) arising from a use of ‘expr’
• In the expression: expr 3 2 :: String
In an equation for ‘it’: it = expr 3 2 :: String
<interactive>:37:6: error:
• No instance for (Num String) arising from the literal ‘3’
• In the first argument of ‘expr’, namely ‘3’
In the expression: expr 3 2 :: String
In an equation for ‘it’: it = expr 3 2 :: String
*Main> expr 3 2 :: Integer
<interactive>:38:1: error:
• No instance for (Fractional Integer) arising from a use of ‘expr’
• In the expression: expr 3 2 :: Integer
In an equation for ‘it’: it = expr 3 2 :: Integer
As mentioned in the comments, operator /
, just like for + - *, forces its two operands to have the same type (and that's also the type of the result). Operator ^
is an exception, and its result has to have the same type as its left operand. Note that for floating-point types, you also have the **
exponentiation operator à la Fortran.
Rules are explained in more detail in this tutorial.
Unfortunately that means that mixed-mode arithmetics is somewhat less easy to get in Haskell than in some well-known imperative languages. If need be, conversion function fromIntegral :: (Integral a, Num b) => a -> b can be used. It gives the compiler license to insert some appropriate conversion.
For the present situation, if a broad type signature is desired, it can be achieved for example like this:
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE ExplicitForAll #-}
fact :: Integral nt => nt -> nt
fact n = if (n <= 0) then 1 else n * fact (n - 1)
expr :: forall nt ft. (Integral nt, Fractional ft) => nt -> ft -> ft
expr n x = (x ^ n) / ((fromIntegral (fact n)) :: ft)
Testing under ghci
:
$ ghci
GHCi, version 8.6.5: http://www.haskell.org/ghc/ :? for help
λ>
λ> :load q65254539.hs
...
Ok, one module loaded.
λ>
λ> expr 2 3
4.5
λ> expr 2 pi
4.934802200544679
λ>
λ> expr 3 (4::Double)
10.666666666666666
λ>