Bueno, no es parte del estándar Haskell 2010, por lo que no está activado por defecto, y se ofrece como una extensión de idioma. En cuanto a por qué no está en el estándar, los tipos de rango-n son bastante más difíciles de implementar que los tipos normales de rango 1 que tiene Haskell; tampoco son necesarios con tanta frecuencia, por lo que el Comité probablemente decidió no molestarse con ellos por razones de simplicidad de lenguaje e implementación.
Por supuesto, eso no significa que los tipos rank-n no sean útiles; lo son, mucho, y sin ellos no tendríamos herramientas valiosas como el ST
monad (que ofrece un estado mutable local eficiente, como IO
, donde todo lo que puede hacer es usar IORef
s). Pero agregan bastante complejidad al lenguaje y pueden causar un comportamiento extraño al aplicar transformaciones de código aparentemente benignas. Por ejemplo, algunos verificadores de tipo rank-n permitirán runST (do { ... })
pero rechazan runST $ do { ... }
, aunque las dos expresiones son siempre equivalentes sin los tipos rank-n. Consulte this SO question para ver un ejemplo del comportamiento inesperado (ya veces molesto) que puede causar.
Si, como sepp2k pregunta, que está en lugar de preguntar por qué forall
tiene que ser añadido de forma explícita al tipo de firmas para conseguir el aumento de la generalidad, el problema es que (forall x. x -> f x) -> (a, b) -> (f a, f b)
es en realidad un tipo más restrictivo que (x -> f x) -> (a, b) -> (f a, f b)
. Con este último, puede pasar cualquier función del formulario x -> f x
(para cualquier f
y x
), pero con el primero, la función que pasa debe funcionar para todox
. Entonces, por ejemplo, una función de tipo String -> IO String
sería un argumento permisible para la segunda función, pero no la primera; debería tener el tipo a -> IO a
en su lugar. ¡Sería bastante confuso si este último se transformara automáticamente en el primero! Son dos tipos muy diferentes.
Podría tener más sentido con los implícitos forall
s explicitados:
forall f x a b. (x -> f x) -> (a, b) -> (f a, f b)
forall f a b. (forall x. x -> f x) -> (a, b) -> (f a, f b)
¿Está preguntando por qué la extensión no está activada por defecto o por qué '(x -> fx) -> (a, b) -> (fa, fb) 'no se trata igual que' (forall x. x -> fx) -> (a, b) -> (fa, fb) '? Si es el último, ¿puede especificar la lógica mediante la cual propone que el compilador decida dónde insertar el 'forall's? – sepp2k
¡Lo último, y no sabría por dónde empezar a proponer nada sobre este tema! –
Tenga en cuenta que el tipo '(x -> f x) -> (a, b) -> (f a, f b)' es bastante inútil. La función no puede aplicar el primer argumento a ninguno de los elementos de la tupla, por lo que su resultado debe ser '⊥' o' (⊥, ⊥) '. – hammar