Haskell 模式匹配后的多态性丢失

Haskell 模式匹配后的多态性丢失,haskell,polymorphism,pattern-matching,Haskell,Polymorphism,Pattern Matching,以下代码用于生成双精度或整数s被假定为negate或idn整个部分;和f小数部分或Nothing表示整数 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)

以下代码用于生成双精度或整数
s
被假定为
negate
id
<代码>n整个部分;和
f
小数部分或
Nothing
表示整数

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)
当我编译这个时,我得到:

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

编译器似乎不知何故忘记了
s
是多态的这一事实。这里发生了什么以及如何修复它?

s
在函数内部不是多态的:您可以使用任何在某个
Num
实例上工作的函数作为此参数,它可能是只在
复杂的
上工作的函数!您需要的是一个通用的量化函数
s
,即可以用任何
Num
实例调用的函数

{-# 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)
那就行了:

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

有趣!我已经找到了错误的地方(它真的想要一个
或者一个a
)作为回报,但我没有意识到有办法解决它。@leftaroundabout:你实际上需要普遍量化的
s
,排名2的签名就是这样做的<代码>存在量化
在这个例子中什么都不做,重要的扩展是
Rank2Types
而已。@Vitus:啊,对!我一直把它混在一起,但仔细想想,这更有意义。编辑。