17

私が関数を持っているとしましょう:

f :: Int -> (Rational, Integer)
f b = ((toRational b)+1,(toInteger b)+1)

(+1)を次のように抽象化したい:

f :: Int -> (Rational, Integer)
f b = (h (toRational b)
      ,h (toInteger b))
    where h = (+1)

これは明らかに機能しませんが、型署名を指定すると機能します。

f :: Int -> (Rational, Integer)
f b = (h (toRational b)
      ,h (toInteger b))
    where h :: Num a => a -> a
          h = (+1)

ここで、hをパラメーターとして渡すことにより、関数をさらに抽象化するとします。

f :: Num a => Int -> (a -> a) -> (Rational, Integer)
f b g = (h (toRational b)
        ,h (toInteger b))
    where h :: Num a => a -> a
          h = g

内側のaが外側のaと同じではないというエラーが表示されます。

この関数を正しく書く方法を知っている人はいますか?gポリモーフィック関数をに渡して、ポリモーフィックに使用したいと思いfます。

私は今、非常に異なるプロジェクトでこの状況に何度も遭遇しましたが、良い解決策を見つけることができませんでした。

4

1 に答える 1

18

私は解決策を見つけました: forall 量指定子を次のように使用します:

{-# LANGUAGE RankNTypes #-}
f :: Int -> (forall a. Num a=> a -> a) -> (Rational, Integer)
f b g = (h (toRational b)
        ,h (toInteger b))
    where h :: Num a => a -> a
          h = g

もちろん、これは次のように変換できます。

f :: Int -> (forall a. Num a=>a -> a) -> (Rational, Integer)
f b g = (g (toRational b)
        ,g (toInteger b))
于 2013-02-14T00:26:24.537 に答える