Pergunta

Atualmente, estou trabalhando no projeto com Haskell e me encontrei alguns problemas. Eu deveria ler e inserir em uma lista cada linha em um arquivo "dictionary.txt", mas não consigo fazê -lo. Eu tenho este código:

main = do
    let list = []
    loadNums "dictionary.txt" list

loadNums location list = do
    inh <- openFile location ReadMode
    mainloop inh list
    hClose inh

mainloop inh list = do 
    ineof <- hIsEOF inh
    if ineof
        then return ()
        else do 
            inpStr <- hGetLine inh
            inpStr:list
            mainloop inh list

Ele deve obter todas as linhas (eu sei que ela recebe todas as linhas, pois substitui a "inpstr: list" por um "putstrln inpstr" funciona corretamente, exibindo todas as linhas) e insira -a em uma lista, mas recebo o seguinte erro :

Couldn't match expected type `IO' against inferred type `[]'

Provavelmente porque a linha HGET não é uma string, mas uma string de IO, que não tenho idéia de como lidar para obter uma string adequada que posso inserir na minha lista. Não tenho idéia de como isso pode ser resolvido, ou qual é exatamente o problema, mas se alguém tiver alguma idéia de como colocar corretamente todas as linhas em um arquivo em uma lista, eu o apreciaria.

Desde já, obrigado!

Foi útil?

Solução

Na linha em que o erro acontece, Haskell está esperando "IO A", mas você está dando um []. Simplificando muito as coisas, em um bloqueio da Mônada de IO, todas as linhas são:

  • Algo que retorna um valor do tipo "io a"; O valor do tipo "A" dentro dele é descartado (então o "a" é frequentemente "()")
  • A <- expressão, que faz a mesma coisa, mas em vez de descartar o valor do tipo "A", dá o nome à esquerda do <-
  • Um LET, que não faz nada mais do que dar um nome a um valor

Nesse bloqueio, o "HGETLINE IN" retorna uma "string io", e a string dentro dela é extraída e dados o nome INPSTR. A próxima linha, já que não é um LET ou A <-, deve ter um tipo "IO A", o que não (causando o erro do compilador). O que você pode fazer, já que você já tem a string, é um LET:

let list' = inpStr:list

Isso cria uma nova lista que consiste na sequência seguida pela lista original e fornece o nome de "List '".

Altere a linha a seguir para usar a "Lista" "em vez de" Lista "(passando assim a nova lista). Essa linha chama (recursivamente) Mainloop, que lerá mais uma linha, se chamará e assim por diante. Depois de ler o arquivo inteiro, ele retornará algo com o tipo "io ()". Este "io ()" será devolvido ao bloco DO no loadnums. Parabéns, você acabou de criar uma lista com as linhas lidas no arquivo, em ordem inversa (já que estava anexando ao chefe da lista) e depois não fez nada.

Se você quiser fazer algo, altere o "return ()" para "Lista de retorno"; O retorno gerará um valor do tipo "io [string], com a lista dentro dela (o retorno não faz nada mais do que encapsular o valor), que você pode extrair no loadnums com a sintaxe <-.

O resto é deixado como um exercício para o leitor.

Outras dicas

A menos que seja para a lição de casa ou algo assim, não há razão para usar muito esforço. A reutilização é preguiçosa!

getLines = liftM lines . readFile

main = do
    list <- getLines "dictionary.txt"
    mapM_ putStrLn list

Mas, como você ainda está aprendendo Haskell, é importante que você entenda o que Cesarb escreveu.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top