问题
Say I have a function:
f :: Int -> (Rational, Integer)
f b = ((toRational b)+1,(toInteger b)+1)
I want to abstract away the (+1) like so:
f :: Int -> (Rational, Integer)
f b = (h (toRational b)
,h (toInteger b))
where h = (+1)
This wont work obviously, but if I specify the type signature it will work:
f :: Int -> (Rational, Integer)
f b = (h (toRational b)
,h (toInteger b))
where h :: Num a => a -> a
h = (+1)
Say I now want to further abstract the function by passing h as a parameter:
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
I get an error that the inner a is not the same a as the outer one.
Does anyone know how to write this function correctly?
I want to pass a polymorphic function g
to f
and use it polymorphically.
I have encountered this situation multiple times now in very different projects, and I could not find a good solution.
回答1:
I found the solution: using the forall quantifier like so:
{-# 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
Which of course can be turned into:
f :: Int -> (forall a. Num a=>a -> a) -> (Rational, Integer)
f b g = (g (toRational b)
,g (toInteger b))
来源:https://stackoverflow.com/questions/14865734/referential-transparency-with-polymorphism-in-haskell