tipos operadores logicos ejemplos datos aritmeticos haskell polymorphism referential-transparency higher-rank-types

ejemplos - operadores logicos y aritmeticos en haskell



Transparencia referencial con polimorfismo en Haskell. (1)

Encontré la solución: usando el cuantificador forall así:

{-# 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

Que por supuesto se puede convertir en:

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

Digamos que tengo una función:

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

Quiero abstraer el (+1) así:

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

Obviamente, esto no funcionará, pero si especifico la firma de tipo funcionará:

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

Digamos que ahora quiero abstraer más la función pasando h como parámetro:

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

Me da un error que la a interna no es la misma que la externa.

¿Alguien sabe cómo escribir esta función correctamente? Quiero pasar una función polimórfica g a f y usarla polimórficamente.

He encontrado esta situación varias veces ahora en proyectos muy diferentes, y no pude encontrar una buena solución.