我如何读取haskell中的文件?

时间:2016-06-04 12:19:45

标签: haskell

我是初学者,我试图从我的文件夹“文件”中读取文件(与脚本相同的路径),但我有下一个错误:

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

这是我的模块Documento的代码:

模块Documento

data Documento = Documento {revista :: String, idD :: String, anno :: String, titulo :: String, resumen :: String, secciones :: [String]} deriving (Eq)
type Documentos = [Documento]

谢谢!

1 个答案:

答案 0 :(得分:0)

您遇到的问题是您正在尝试调用一个接收[FilePath]的函数,但是您正在调用IO [FilePath]

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

例如,函数getLines从用户获取一行输入,并且由于每次都不能保证用户输入的行相同,因此该函数返回IO String而不是String而不是常规unsafePerformIO :: IO a -> a

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

因此,通常不鼓励使用函数reader :: IO [Documento] reader = do setCurrentDirectory "papers" directorio <- getCurrentDirectory putStrLn directorio -- Directorio donde estan los documentos let pathFicheros = getDirectoryContents directorio return (leerDocumentos pathFicheros) ,因为它执行IO操作而不跟踪IO已执行的事实。

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

使用IO值或任何其他类型的monadic值时,您需要一种方法来处理monad中保存的值,并暂时忽略值周围的monadic上下文。

有几种方法可以做到这一点。在您的情况下,您可能希望使用do notation,因为您已经使用了它。

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

let pathFicheros = getDirectoryContents directorio
return (leerDocumentos pathFicheros)

具体来说,您遇到的错误包括以下几行:

leerDocumentos :: [FilePath] -> [Documento]

问题在于您尝试拨打pathFicheros并传入IO [FIlePath] getDirectoryContents :: FilePath -> IO [FilePath],因为它是通过致电pathFicheros获得的。

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

由于您在do块中执行了所有这些操作,因此您可以使用pathFicheros运算符将IO上下文放入do块,并将包含的值仅分配给常量{{1} }。

pathFicheros <- getDirectoryContents directorio
return (leerDocumentos pathFicheros)

这样,您可以将pathFicheros用作[FilePath],但将IO上下文保留在reader :: IO [Documento]函数返回的值内。

进行更改后,代码应该编译而不会出现问题。

但是,您还需要删除unsafePerformIOleerDocumentos的使用情况,并将其替换为do块中的相应功能,然后应该返回IO [Documento]而不仅仅是[Documento]一个return。之后,您只需要在reader的末尾删除return的使用,留下>>=内的内容,您应该很好。

我建议你做一些阅读和试验monad,并且常用函数与monad一起工作,例如“bind”函数IO,这应该可以帮助你更好地理解如何与lists=may['barrier'] lists def column(matrix, i): return [row[i] for row in matrix] column(lists,0) barr_col=column(lists,0) barr_col 等单子一起使用。

Monads是Haskell最初难以理解的概念,但是你可以做的最好的事情就是阅读它们并尝试实现你正在阅读的想法。