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.

¿Fue útil?

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top