7

次のコードは、Double または Integer のいずれかを生成することを目的としています。または のいずれかsであると想定されます。全体の部分; 小数部分または整数の場合。negateidnfNothing

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 に答える