que era tanto sueño que escribí el siguiente código (modificado para mostrar sólo la confusión):Haskell: ¿Por qué no hay desajuste de tipo (y por qué compila esto)?
fac s = take 10 [s, s `mod` 1 ..]
maxFactor x = if (s == [])
then x
else head <-- this should be 'head x' instead of just 'head'
where s = fac x
Sin embargo, esta carga en ghci (y compila) muy bien. Cuando ejecuté maxFactor 1
, se queja (por supuesto):
<interactive>:0:1:
No instance for (Integral ([a0] -> a0))
arising from a use of `maxFactor'
Possible fix:
add an instance declaration for (Integral ([a0] -> a0))
In the expression: maxFactor 1
In an equation for `it': it = maxFactor 1
<interactive>:0:11:
No instance for (Num ([a0] -> a0))
arising from the literal `1'
Possible fix: add an instance declaration for (Num ([a0] -> a0))
In the first argument of `maxFactor', namely `1'
In the expression: maxFactor 1
In an equation for `it': it = maxFactor 1
Sin embargo, no entiendo este comportamiento:
fac
's tipo es:
fac :: Integral a => a -> [a]
mientras maxFactor
' s tipo es:
maxFactor :: Integral ([a] -> a) => ([a] -> a) -> [a] -> a
Does not mean th th e siguiente:
- la primera entrada a
fac
debe ser de clase de tiposIntegral
(por ejemplo,fac 10
); - ya que en la definición de
maxFactor
, no esfac x
, x debe ser también de clase de tiposIntegral
, por lo tanto, el tipomaxFactor
's sería empezar con algo comomaxFactor :: (Integral a) => a ->
... luego algo más? Sin embargo, si ese es el caso, entonces ¿por qué este código se compila ya que el retorno demaxFactor
puede serx
ohead
, que al seguir esta línea de razonamiento, no tiene el mismo tipo?
¿Qué es lo que falta aquí?
¡Gracias por cualquier entrada por adelantado!
Este tipo de problema puede surgir de una manera mucho más simple. Sospecho (pero no soy un experto) que puede suceder cuando el verificador de tipos no puede reducir suficientemente una expresión. Por ejemplo, foo x = 1 + x; bar = foo head - fallará, pero foo x = 1 + x; bar x = foo head: se compilará. – Sarah
@Sarah: el ejemplo que proporciona no comprueba de forma automática debido a la restricción de monomorfismo; si agrega pragma, tipea (aunque hay un problema sutil: GHCi infiere tipo 'Num ([a] → a) ⇒ [a] → a' y usted no puede declarar' bar' con este tipo, usted necesitaría FlexibleContexts para eso) – Vitus
Por lo que vale, si compila con '-Wall' (o lo agrega a sus opciones de ghci predeterminadas, para que ghci" compile "con' -Wall') obtendrá una advertencia porque no puso un tipo firma en 'maxFactor'. Entonces, presumiblemente, escribirás 'maxFactor :: Integral a => a -> a' y no podrá compilarse. – MatrixFrog