tipos - Haskell: YesNo tipo de clase. ¿Por qué Integer?
string en haskell (3)
Entonces, ¿esto significa que cuando escribo un número entero en GHCi, generalmente asume que su valor es Integer?
Sí. Básicamente, GHCi primero intentará con Integer
, luego, si eso falla, Double
y luego finally ()
para resolver restricciones de tipo ambiguas. Puede leer los detalles sobre cómo funciona esto en la Guía del usuario de GHC .
Sin embargo, tenga en cuenta que en los módulos compilados, las reglas son un poco más estrictas. En particular, la configuración predeterminada solo se aplica a las clases estándar, por lo que su ejemplo no funcionará sin una anotación de tipo en un módulo compilado a menos que habilite la extensión ExtendedDefaultRules
que le brinda el mismo comportamiento que GHCi.
Tengo una pregunta sobre cómo GHCi asume el tipo de un número entero.
Estaba leyendo Sí-No tipo de clase de Learn you a Haskell.
Aquí hay un enlace si quieres leer todo. http://learnyouahaskell.com/making-our-own-types-and-typeclasses#a-yes-no-typeclass
Para decirlo brevemente, este capítulo muestra que al definir mi propia clase, puedo hacer una función que funcione con muchos tipos.
Este libro define la clase YesNo con una función.
yesno :: a -> Bool
y hacer Int
como una instancia de clase YesNo
instance YesNo Int where
yesno 0 = False
yesno _ = True
Cuando cargué esto en mi GHCi y escribí
yesno 0
devolvió el error. Pensé que probablemente es porque GHCi no puede decir si 0 está destinado a ser Int
Integer
Double
u otro tipo en la clase Num
. En realidad, cuando escribí yesno (0 :: Int) funcionó.
Así que solo por diversión hice Integer
como una instancia de la clase YesNo
y escribí
instance YesNo Integer where
yesno 0 = True
yesno _ = False
(Note que volteé Verdadero y Falso) y otra vez, escribí
yesno 0
(Sin ninguna declaración de tipo), entonces GHCi mostró True
.
Por otra parte, cuando escribí
yesno $ fromIntegral 0
devolvió True
, lo que significa que GHCi piensa que el tipo de fromIntegral 0
es Integer
.
Entonces, ¿esto significa que cuando escribo un número entero en GHCi, generalmente asume que su valor es Integer
en lugar de? Estoy confundido porque :t 0
devuelve Num a => a
Es el tipo predeterminado junto con las reglas predeterminadas extendidas de ghci.
Los literales enteros son polimórficos, tienen el tipo Num a => a
(ya que representan el fromInteger literal
). Pero cuando se evalúa una expresión, necesaria para imprimir su resultado, por ejemplo, la expresión debe recibir un tipo monomórfico.
Por sí mismo,
yesno 0
impone las dos restricciones Num a
y YesNo a
en el 0
, y toda la expresión tendría el tipo ambiguo
yesno 0 :: (Num a, YesNo a) => Bool
(Es ambiguo, ya que la variable de tipo en la restricción no es accesible desde el tipo a la derecha de =>
).
En general, los tipos ambiguos son errores de tipo, sin embargo, en algunos casos, la ambigüedad se resuelve al crear una instancia de la variable de tipo restringido con un tipo predeterminado. Las reglas en la especificación de lenguaje son que una variable de tipo puede ser predeterminada si
En situaciones en las que se descubre un tipo ambiguo, una variable de tipo ambigua,
v
, es definible si:
- `v` appears only in constraints of the form `C v`, where `C` is a class, and
- at least one of these classes is a numeric class, (that is, `Num` or a subclass of `Num`), and
- all of these classes are defined in the Prelude or a standard library (Figures 6.2–6.3 show the numeric classes, and Figure 6.1 shows the classes defined in the Prelude.)
La restricción (Num a, YesNo a)
cumple los dos primeros requisitos, pero no el tercero. Por lo tanto, según el estándar de idioma, no es predeterminado y debería ser un error de tipo.
Sin embargo, ghci usa reglas predeterminadas extendidas y también variables predeterminadas de tipo restringido por clases no definidas en Prelude o las bibliotecas estándar.
Entonces, aquí elegiría el valor predeterminado para una restricción Num
, a menos que haya una declaración explícita predeterminada dentro del alcance, que sea Integer
o, si Integer
no satisface las restricciones, se intenta el Double
.
Por lo tanto, cuando tenga una instance YesNo Integer
, ghci puede predeterminar con éxito la variable de tipo a Integer
. Pero sin una instancia de este tipo disponible, el incumplimiento falla porque ninguno de los candidatos predeterminados tiene una instancia.
en el primer caso intenta escribir:
Prelude> yesno (0 :: Int)
False