Una función de Haskell de tipo: IO String> Cadena
Pregunta
he escrito un montón de código en Haskell para crear un índice de texto. La función de la parte superior se ve así:
index :: String -> [(String, [Integer])]
index a = [...]
Ahora quiero dar a esta función una cadena leer desde un archivo:
index readFile "input.txt"
Lo que no funcionará porque readFile es de tipo FilePath -.> IO cadena
No se pudo tipo coincide con el esperado 'Cadena' contra el tipo inferido 'IO cadena'
Veo el error, pero no puedo encontrar ninguna función con el tipo:
IO String -> String
Creo que la clave del éxito está en algún lugar bajo unas mónadas, pero no pude encontrar una manera de resolver mi problema.
Solución
Puede fácilmente lo suficientemente escribir una función que llama a la acción readFile, y pasa el resultado a su función de índice.
readAndIndex fileName = do
text <- readFile fileName
return $ index text
Sin embargo, la mónada IO contamina todo lo que lo utiliza, por lo que esta función tiene el tipo:
readAndIndex :: FilePath -> IO [(String, [Integer])]
Otros consejos
Hay una muy buena razón por la que no hay tal función.
Haskell tiene la noción de pureza funcional. Esto significa que una función siempre devolverá el mismo resultado cuando se le llama con los mismos parámetros. La solamente lugar donde se permite IO está dentro de la mónada IO.
Si hubo una función *
index :: IO String -> String
entonces podríamos hacer acciones repente IO en cualquier lugar llamando, por ejemplo:
index (launchMissiles >> deleteRoot >> return "PWNd!")
pureza funcional es una característica muy útil que no queremos perder, ya que permite que el compilador para reordenar las funciones en línea y mucho más libremente, que se puede desencadenó a diferentes núcleos sin cambiar la semántica y también da la programadores una sensación de seguridad ya que si se puede saber qué función puede y no puede hacer a partir de su tipo.
* En realidad, hay es tal función. Se llama unsafePerformIO
y se llama así por muy, muy buenas razones. No utilice a menos que estés 100% seguro de lo que está haciendo!
Bueno, no puede deshacerse de la parte IO
mónada de IO String
. Eso significa que usted tendrá que hacer su IO [(String, [Integer])]
retorno de la función.
Yo recomiendo aprender más acerca de las mónadas, pero por ahora se puede salirse con la función liftM
:
liftM index (readFile "input.txt")
liftM
tiene esta firma:
liftM :: Monad m => (a -> b) -> m a -> m b
Se necesita una función no monádica y la transforma en una función monádica.
fmap index $ readFile "input.txt"
o
readFile "input.txt" >>= return . index
Es posible que desee ver en la mónada y funtores