如何读取haskell中的文件?

如何读取haskell中的文件?,haskell,Haskell,我是初学者,正在尝试从我的文件夹“papers”(与脚本路径相同)中读取文件,但我遇到了下一个错误: Couldn't match expected type ‘[FilePath]’ with actual type ‘IO [FilePath]’ In the first argument of ‘leerDocumentos’, namely ‘pathFicheros’ In the first argument of ‘return’,

我是初学者,正在尝试从我的文件夹“papers”(与脚本路径相同)中读取文件,但我遇到了下一个错误:

Couldn't match expected type ‘[FilePath]’
                with actual type ‘IO [FilePath]’
    In the first argument of ‘leerDocumentos’, namely ‘pathFicheros’
    In the first argument of ‘return’, namely
      ‘(leerDocumentos pathFicheros)’
也许这不是我代码中的一个错误,所以我希望有人能帮助我完成我的模块

我的读者的代码是:

module LeerDocumentos2 where
import System.Directory
import System.IO.Unsafe
import System.IO()
import Documento


reader :: IO [Documento]
reader = do
    setCurrentDirectory "papers"
    directorio <- getCurrentDirectory
    putStrLn directorio       -- Directorio donde estan los documentos
    let pathFicheros = getDirectoryContents directorio
    return (leerDocumentos pathFicheros)

leerDocumentos :: [FilePath] -> [Documento]
leerDocumentos [] = []
leerDocumentos (x:xs) = do
                    let documento = unsafePerformIO (leerDocumento x)
                    [documento]++ leerDocumentos xs
leerDocumento :: String -> IO Documento
leerDocumento ruta = do
                putStrLn ruta
                texto <- readFile ruta
                let docuAux = lines texto
                let revista = obtenerRevista docuAux
                let idd = obtenerID docuAux
                let anno = obtenerAnno docuAux
                let titulo = obtenerTitulo docuAux
                let resumen = obtenerResumen docuAux
                let secciones = obtenerSecciones docuAux
                let documento = D (revista,idd,anno,titulo,resumen,secciones)
                return documento

obtenerRevista :: [String] -> String
obtenerRevista [] = []
obtenerRevista texto = head texto

obtenerID:: [String] -> String
obtenerID [] = []
obtenerID texto =  head (drop 1 (texto))

obtenerAnno:: [String] -> String
obtenerAnno [] = []
obtenerAnno texto =  head (drop 2 (texto))

obtenerTitulo:: [String] -> String
obtenerTitulo [] = []
obtenerTitulo texto =  head (drop 4 (texto))

obtenerResumen:: [String] -> String
obtenerResumen [] = []
obtenerResumen texto =  head (drop 6 (texto))

obtenerSecciones :: [String]->[String]
obtenerSecciones [] = []
obtenerSecciones texto = quitarSeparador (drop 8 (texto))

quitarSeparador :: [String] -> [String]
quitarSeparador [] = []
quitarSeparador (s:sn) = if s == "--" || length s <= 1 then --Para quitar lineas blancas
                            quitarSeparador sn
                          else
                            s:quitarSeparador sn

谢谢

您遇到的问题是,您试图调用一个函数,该函数接受一个
[FilePath]
,但您正在向它传递一个
IO[FilePath]

问题是要传递给函数的值被封装在
IO
Monad中。每当使用输入/输出操作进行计算时,
IO
Monad中就会保存一个值。在这种情况下,
IO
Monad基本上是说一些IO是用来创建值的,因此调用生成值的函数可能并不总是在相同的输入上生成相同的输出

例如,函数
getLines
从用户那里获取一行输入,并且由于不能保证用户每次输入的行都是相同的,因此函数返回一个
IO字符串
,而不是常规的
字符串

在Haskell中,您总是希望跟踪何时使用输入/输出。因此,您通常不会使用接受IO值并返回非IO值的函数,因为这会破坏重要的上下文

因此,通常不鼓励使用函数
unsafePerformIO::IO a->a
,因为它执行IO操作时没有跟踪IO已执行的事实


这就是你所面临的问题背后的理论,现在你知道了,你可以想出如何处理这个问题

当使用IO值或任何其他类型的一元值时,您需要一种方法来使用一元中的值,并暂时忽略该值周围的一元上下文

有几种方法可以做到这一点。在您的例子中,您可能希望使用do符号,因为您已经在使用它了

让我们看看您遇到问题的部分:

reader :: IO [Documento]
reader = do
    setCurrentDirectory "papers"
    directorio <- getCurrentDirectory
    putStrLn directorio       -- Directorio donde estan los documentos
    let pathFicheros = getDirectoryContents directorio
    return (leerDocumentos pathFicheros)
问题是您试图调用
leerDocumentos::[FilePath]->[Documento]
并传入类型为
IO[FilePath]
pathFicheros
,因为它是通过调用
getDirectoryContents::FilePath->IO[FilePath]
获得的

您要做的是找到一种方法,将
pathFicheros
作为
[FilePath]
使用,但要保留IO上下文

由于所有这些都是在do块中完成的,因此可以使用
=
,这将帮助您更好地了解如何使用单子,例如
IO


一开始在Haskell中,单子是一个很难理解的概念,但要想更好地使用单子,最好的办法是仔细阅读它们,并尝试实现您正在阅读的想法。

首先请暂时忘记,
unsafePerfomIO
甚至存在,然后使用
pathFicheros
reader :: IO [Documento]
reader = do
    setCurrentDirectory "papers"
    directorio <- getCurrentDirectory
    putStrLn directorio       -- Directorio donde estan los documentos
    let pathFicheros = getDirectoryContents directorio
    return (leerDocumentos pathFicheros)
let pathFicheros = getDirectoryContents directorio
return (leerDocumentos pathFicheros)
pathFicheros <- getDirectoryContents directorio
return (leerDocumentos pathFicheros)