Loss of polymorphism after pattern matching

haskell, pattern-matching, polymorphism

Solution

`s` is not polymorphic from inside of your function: you can use any function that works on some `Num` instance as this parameter, it might be a function that only works on `Complex`! What you need is an universally quantified function `s`, i.e. one that can actually be called with any `Num` instance.

{-# LANGUAGE Rank2Types #-}

computeValue :: (forall a . Num a => a->a) -> Integer -> Maybe Double -> Either Double Integer
computeValue s n Nothing = Right $ s n
computeValue s n (Just a) = Left $ s (fromIntegral n + a)

That works then:

Prelude Data.Either> computeValue id 3 Nothing
Right 3
Prelude Data.Either> computeValue negate 57 (Just pi)
Left (-60.1415926535898)

Problem

The following code is intended to produce either a Double or an Integer. `s` is assumed to be either `negate` or `id`; `n` the whole part; and `f` the fractional part or `Nothing` for an integer. ``` computeValue :: Num a => (a->a) -> Integer -> (Maybe Double) -> Either Double Integer computeValue s n Nothing = Right $ s n computeValue s n (Just a) = Left $ s (fromIntegral n + a) ``` when I compile this I get: ``` test1.hs:2:28: Couldn't match type `Integer' with `Double' Expected type: Either Double Integer Actual type: Either Double a In the expression: Right $ s n In an equation for `computeValue': computeValue s n Nothing = Right $ s n test1.hs:2:38: Couldn't match type `Integer' with `Double' In the first argument of `s', namely `n' In the second argument of `($)', namely `s n' In the expression: Right $ s n ``` It seems like somehow the compiler has lost track of the fact that `s` is polymorphic. What happened here and how do I fix it?

Original source