Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

exp x in Haskell and type signature

Tags:

haskell

ghc

ghci

I defined the custom exponentiation exp' function in GHCi as:

let exp' x = sum $ take 100 [(x**k) / factorial k | k <- [0..]]

which yields the following type signature:

#> :t exp'
exp' :: (Enum a, Floating a) => a -> a

However, I would have expected it to match that of the exp function, i.e.

#> :t exp
exp :: Floating a => a -> a

Can anybody explain the Enum a => a type constraint of my exp' function? Why isn't it just Floating a => a?

Thanks.

like image 493
VH-NZZ Avatar asked Mar 20 '23 04:03

VH-NZZ


1 Answers

It originates from the k <- [0..] - that desugars to use the Enum class.

It then propagates into the final type signature because you're using (**) for exponentiation which expects its arguments to be the same type:

(**) :: Floating a => a -> a -> a

One option is to use (^) for exponentiation instead:

(^) :: (Integral b, Num a) => a -> b -> a

You'll also need to convert factorial k to the right type, with something like fromIntegral:

exp' x = sum $ take 100 [(x^k) / fromIntegral (factorial k) | k <- [0..]]

It's possibly a better fit for this case because your exponents will be integers, although it may be a bit less efficient as it uses repeated multiplication (logarithmic in the exponent) rather than constant-time floating point operations.

Alternatively (as suggested in a comment), to stick with (**), use fromIntegral to move from an enumeration over Int to the actual type you are working with:

let exp' x = sum $ take 100 [(x**fromIntegral k) / fromIntegral (factorial k)
                                                        | k <- [0..]]
like image 146
GS - Apologise to Monica Avatar answered Mar 28 '23 03:03

GS - Apologise to Monica