Подтвердить что ты не робот

Ссылочная прозрачность с полиморфизмом в Haskell

Скажем, у меня есть функция:

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

Я получаю ошибку, что внутренняя а не такая же, как внешняя.

Кто-нибудь знает, как правильно записать эту функцию? Я хочу передать полиморфную функцию g в f и использовать ее полиморфно.

Я столкнулся с этой ситуацией несколько раз сейчас в очень разных проектах, и я не нашел хорошего решения.

4b9b3361

Ответ 1

Я нашел решение: используя квант 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))