Esta es una de las pequeñas cosas engañosas que me confundieron cuando probé Haskell por primera vez. Está malinterpretando el significado de la construcción <-
en notación de Do. result <- f handle
no significa "asignar el valor de f handle
a result
"; significa "enlazar result
a un valor 'extraído' del valor monádico de f handle
" (donde la 'extracción' ocurre de algún modo definido por la instancia particular de Monad que está utilizando, en este caso la mónima IO).
es decir, por alguna clase de tipos Monad m, la declaración <-
toma una expresión de tipo m a
en el lado derecho y una variable de tipo a
en el lado de la mano izquierda, y se une la variable a un valor. Por lo tanto, en su ejemplo particular, con result <- f handle
, tenemos los tipos f result :: IO a
, result :: a
y return result :: IO a
.
PD-notación tiene también una forma especial de let
(sin la palabra clave in
en este caso!) Que funciona como contraparte a pura <-
. Por lo que podría volver a escribir tu ejemplo como:
withFile' :: FilePath -> IOMode -> (Handle -> IO a) -> IO a
withFile' path mode f = do
handle <- openFile path mode
let result = f handle
hClose handle
result
En este caso, debido a que el let
es una tarea sencilla, el tipo de result
es IO a
.
Oh d'oh! Completamente perdido el operador _sucking_ '<-'! – drozzy
También podría ser 'let result = f handle; hCerrar el mango; ¿result? o no logré comprender la mónada nuevamente? – delnan
@delnan que sería 'do {handle <- openFile mode path; hCerrar el mango; f manejar; } ', entonces' f handle' probablemente se quejaría de un identificador cerrado. –