参考透明度与Haskell中的多态性

时间:2013-02-14 00:16:43

标签: haskell polymorphism referential-transparency higher-rank-types

说我有一个功能:

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并以多态方式使用它。

我现在在非常不同的项目中多次遇到过这种情况,我找不到一个好的解决方案。

1 个答案:

答案 0 :(得分: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))