Notación do inconsistente en funciones
Por qué está permitida esta función:
-- function 1
myfunc :: String
myfunc = do
x <- (return True)
show x
y esto no es:
-- function 2
myfunc :: String
myfunc = do
x <- getLine
show x
El error de compilación:
Couldn't match type `[]' with `IO'
Expected type: IO Char
Actual type: String
Entiendo por qué la función 2 no debería funcionar, pero ¿por qué entonces la función 1 funciona?
y por qué esto entonces funciona:
-- function 3
myfunc = do
x <- getLine
return (show x)
Entiendo que regresa IO Stringentonces, pero ¿por qué la función 1 tampoco está obligada a hacer esto?
Respuestas
En function1, el dobloque en myfuncestá trabajando en la lista mónada, porque en Stringrealidad es justo [Char]. Allí, return Truesimplemente crea [True]. Cuando lo haga x <- return Trueque los "extractos" Truefuera de [True]y se une a x. La siguiente línea se show xconvierte Trueen una cadena "True". que siendo el valor de retorno que el compilador espera ver, termina funcionando bien.
Mientras tanto, en function2 , el dobloque en myfunc también está trabajando en la lista mónada (por la misma razón, en Stringrealidad [Char]) pero llama a la getLineque solo está disponible en la IOmónada. Así que, como era de esperar, esto falla.
- EDITAR 1
OP ha agregado una función3
-- function 3
myfunc :: String
myfunc = do
x <- getLine
return (show x)
No, esto no debería funcionar por la misma razón por la que function2 falla.
- EDITAR 2
OP ha actualizado la función 3 para corregir un error de copiar y pegar.
-- function 3
myfunc = do
x <- getLine
return (show x)
Esto se menciona en los comentarios, pero en aras de la claridad, esto funciona porque, cuando el tipo de información no está especificado, GHC hace la mejor inferencia y, después de verlo getLine, calcula que es IO Stringlo que proporciona getLine.
Nota: escribí esta respuesta con un tono tan informal como pude sin equivocarme con la intención de hacerlo accesible para un nivel principiante.
doLos bloques funcionan en el contexto de un arbitrario Monad. El Monad, en este caso, es []. La Monadinstancia de listas se basa en listas por comprensión:
instance Monad [] where
return x = [x]
xs >>= f = [y | x <- xs, y <- f x]
Puede desugar la donotación de la siguiente manera:
myfunc :: String
myfunc = do
x <- (return True)
show x
-- ==>
myfunc = [y | x <- return True, y <- show x]
-- ==>
myfunc = [y | x <- [True], y <- show x]
En una lista de comprensión, x <- [True]es realmente lo mismo que let x = True, porque solo está dibujando un elemento de la lista. Entonces
myfunc = [y | y <- show True]
Por supuesto, "la lista de todos los yque yestán en show True" es justa show True.