Loss of polymorphism after pattern matching

The following code is for creating either Double or Integer. s is considered either negate or id ; n all part; and f fractional part or Nothing for the integer.

 computeValue :: Num a => (a->a) -> Integer -> (Maybe Double) -> Either Double Integer computeValue sn Nothing = Right $ sn computeValue sn (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 $ sn In an equation for `computeValue': computeValue sn Nothing = Right $ sn 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 `sn' In the expression: Right $ sn 

It seems that somehow the compiler has lost information that s is polymorphic. What happened here and how to fix it?

+7
source share
1 answer

s not polymorphic from within your function: you can use any function that works on some Num instance as this parameter, it can be a function that works only on Complex ! You need a universally quantified function s , that is, one that can be called with any instance of Num .

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

This works then:

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

All Articles