7

以下代码旨在生成 Double 或 Integer。s假定为negateid; 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多态的事实。这里发生了什么,我该如何解决?

4

1 回答 1

10

s从你的函数内部不是多态的:你可以使用任何在某个 Num实例上工作的函数作为这个参数,它可能是一个只在Complex! 您需要的是一个普遍量化的函数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)
于 2012-05-23T23:12:36.400 回答