usos usar reservadas poner patrones palabras librerias inferencia imprimir importar comparacion como comentarios haskell polymorphism type-inference monomorphism-restriction

usar - ¿Por qué los valores polimórficos no se infieren en Haskell?



inferencia haskell (2)

Es la restricción de monomorfismo que dice que todos los valores, que se definen sin parámetros y no tienen una anotación de tipo explícito, deben tener un tipo monomórfico. Esta restricción se puede desactivar en ghc y ghci utilizando -XNoMonomorphismRestriction .

El motivo de la restricción es que sin esta restricción long_calculation 42 se evaluaría dos veces, mientras que la mayoría de la gente probablemente esperaría / querría que solo se evaluara una vez:

longCalculation :: Num a => a -> a longCalculation = ... x = longCalculation 42 main = print $ x + x

Los literales numéricos tienen un tipo polimórfico:

*Main> :t 3 3 :: (Num t) => t

Pero si enlace una variable a tal literal, el polimorfismo se pierde:

x = 3 ... *Main> :t x x :: Integer

Si defino una función, por otro lado, es por supuesto polimórfica:

f x = 3 ... *Main> :t f f :: (Num t1) => t -> t1

Podría proporcionar una firma de tipo para asegurar que la x permanezca polimórfica:

x :: Num a => a x = 3 ... *Main> :t x x :: (Num a) => a

Pero, ¿por qué es esto necesario? ¿Por qué no se deduce el tipo polimórfico?


Para expandir la respuesta de sepp2k un poco: si tratas de compilar lo siguiente (o lo cargas en GHCi), obtienes un error:

import Data.List (sort) f = head . sort

Esto es una violación de la restricción de monomorfismo porque tenemos una restricción de clase (introducida por sort ) pero no argumentos explícitos: se nos dice (algo misteriosamente) que tenemos una Ambiguous type variable en la restricción Ord a .

Su ejemplo ( let x = 3 ) tiene una variable de tipo similarmente ambigua, pero no da el mismo error porque las reglas de "default" de Haskell lo guardan:

Cualquier variable de tipo monomórfico que permanezca cuando se complete la inferencia de tipo para un módulo completo se considera ambigua y se resuelve a tipos particulares utilizando las reglas de incumplimiento (Sección 4.3.4).

Consulte esta respuesta para obtener más información acerca de las reglas de incumplimiento: el punto importante es que solo funcionan para ciertas clases numéricas, por lo que x = 3 está bien, mientras que f = sort no.

Como nota al margen: si prefiere que x = 3 termine siendo un Int lugar de un Integer , y y = 3.0 sea ​​un Rational lugar de un Double , puede usar una "declaración predeterminada" para anular las reglas predeterminadas predeterminadas :

default (Int, Rational)