2016-06-04 2 views
-2

новичок Im и им пытаются читать файлы из моей папки «документы» (в том же пути, что сценарии), но у меня есть следующая ошибка:Как я могу читать файлы в 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] 

спасибо !!

+4

сначала забудьте, что 'unsafePerfomIO' даже существует, тогда используйте' pathFicheros <- getDirectoryContents directorio' вместо 'let' – Carsten

ответ

0

Проблема, с которой вы сталкиваетесь, заключается в том, что вы пытаетесь вызвать функцию, которая принимает [FilePath], но вы передаете ей IO [FilePath].

Проблема в том, что значение, которое вы хотите передать в функцию, инкапсулировано в Монастырь IO. Величина удерживается в Монашке IO всякий раз, когда для ее вычисления используется операция ввода/вывода. В этом случае монада IO в основном говорит о том, что для создания значения было выполнено некоторое IO, и поэтому вызов функции, которая генерирует это значение, может не всегда производить один и тот же вывод на одном и том же входе.

Например, функция getLines получает строку ввода от пользователя, и так как линии, что пользователь вводит не может быть гарантирован, чтобы быть таким же, каждый раз, когда функция возвращает IO String, а не обычный String.

В Haskell вы всегда хотите отслеживать, когда используется вход/выход. Таким образом, вы, как правило, не будете работать с функциями, которые принимают значение IO и возвращают значение, отличное от IO, поскольку это разрушает важный контекст.

Таким образом, использование функции unsafePerformIO :: IO a -> a обычно обескуражено, так как оно выполняет операцию ввода-вывода без отслеживания того факта, что выполнено IO.


То есть теория позади вопроса вы столкнулись, теперь, когда вы знаете, что вы можете понять, как справиться с проблемой.

При работе с значениями ввода-вывода или любых других монадических значений вам нужен способ работы со значением, удерживаемым в монаде, и временным игнорированием монадического контекста вокруг значения.

Есть несколько способов, которыми это можно сделать. В вашем случае вы, вероятно, захотите работать с нотной записью, так как вы уже немного ее используете.

Давайте посмотрим на раздел, где вы испытываете проблемы:

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) 

Вопрос заключается в том, что вы пытаясь позвонить leerDocumentos :: [FilePath] -> [Documento] и передать в pathFicheros, который имеет тип IO [FIlePath], так как он получен от звонка getDirectoryContents :: FilePath -> IO [FilePath].

Что вы хотите сделать, это найти способ работы с pathFicheros как только [FilePath], но сохраните контекст IO.

Поскольку вы делаете все это в блоке do, вы можете использовать оператор <- для сортировки патрона IO-контекста до блока do и назначать только содержащееся значение в константу pathFicheros.

pathFicheros <- getDirectoryContents directorio 
return (leerDocumentos pathFicheros) 

Таким образом, вы можете работать с pathFicheros как [FilePath], но сохранить контекст ввода-вывода в пределах значения, возвращаемого функцией reader :: IO [Documento].

После внесения изменений код должен быть скомпилирован без проблем.

Однако, вы также хотите, чтобы удалить использование unsafePerformIO в leerDocumentos и заменить его надлежащего функционирования в блоке Д.О., который должен затем возвращать IO [Documento], а не просто [Documento]. После этого вам просто нужно удалить return в конце reader, оставив в файле return, и вам должно быть хорошо.

Я рекомендую вам почитать и поэкспериментировать с монадами, а общие функции работают с монадами, такими как функция «привязки» >>=, и это должно помочь вам лучше понять, как работать с монадами например IO.

Монады представляют собой сложную концепцию, которую сначала можно понять в Haskell, но лучшее, что вы можете сделать, чтобы улучшить работу с ними, - это прочитать их и попытаться реализовать идеи, о которых вы читаете.

Смежные вопросы