Haskell:ファイルのすべての行をリストに挿入する
質問
現在、Haskellとのプロジェクトに取り組んでいますが、問題がいくつかあります。 <!> quot; dictionary.txt <!> quot;の各行を読み、リストに挿入することになっています。ファイル、しかし私はそうすることができないようです。私はこのコードを持っています:
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
すべての行を取得することになっています(<!> quot; inpStr:list <!> quot;を<!> quot; putStrLn inpStr <!> quot;に置き換えると、すべての行が取得されることがわかります)正しく、すべての行を表示します)、リストに挿入しますが、次のエラーが表示されます:
Couldn't match expected type `IO' against inferred type `[]'
おそらく、hGetLineは文字列ではなく、IO文字列であり、リストに挿入できる適切な文字列を取得するための処理方法がわかりません。これをどのように解決できるか、または問題が正確に何であるかはわかりませんが、ファイル内のすべての行をリストに適切に入れる方法について誰かが知っているなら、私はそれを感謝します。
事前に感謝します!
解決
エラーが発生する行では、Haskellは<!> quot; IO a <!> quot;を期待していますが、[]を指定しています。 IOモナドのdoブロックでは、すべての行が次のいずれかです:
- <!> quot; IO a <!> quot;の値を返す何か。タイプ; <!> quot; a <!> quot;の値その中の型は破棄されます(そのため<!> quot; a <!> quot;はしばしば<!> quot;()<!> quot;)
- A <!> lt;-式。これは同じことを行いますが、<!> quot; a <!> quot;の値を破棄する代わりに使用します。 typeは<!> lt;- の左側に名前を付けます
- 値に名前を付ける以上のことはしませんlet
そのdoブロックでは、<!> quot; hGetLine inh <!> quot; <!> quot; IO String <!> quot;を返し、その中のStringが抽出され、inpStrという名前が付けられます。次の行はletまたは<!> lt;-ではないため、タイプ<!> quot; IO a <!> quot;を持つ必要がありますが、これはありません(したがって、コンパイラエラーが発生します)。すでにStringを持っているので、代わりにできることはletです:
let list' = inpStr:list
これにより、文字列とそれに続く元のリストで構成される新しいリストが作成され、<!> quot; list '<!> quot;という名前が付けられます。
次の行を変更して、<!> quot; list '<!> quot;を使用します。 <!> quot; list <!> quot;の代わりに(したがって、新しいリストを渡します)。その行は(再帰的に)メインループを呼び出します。メインループはもう1行読み取り、それ自体を呼び出します。ファイル全体を読み取った後、<!> quot; IO()<!> quot;で何かを返します。タイプ。この<!> quot; IO()<!> quot; loadNumsでdoブロックに返されます。おめでとうございます。ファイルから読み取った行を逆の順序でリストを作成し(リストの先頭に追加するため)、何もしませんでした。
何かをしたい場合は、<!> quot; return()<!> quot;を変更します。 to <!> quot; return list <!> quot ;;戻り値は<!> quot; IO [String] <!> quot;型の値を生成し、その中にリストが含まれます(戻り値は値をカプセル化するだけです)。これはloadNumsで<!> lt;-構文。
残りは読者への課題として残されています。
他のヒント
これが宿題か何かのためでない限り、そんなに努力する理由はありません。再利用は怠zyです!
getLines = liftM lines . readFile
main = do
list <- getLines "dictionary.txt"
mapM_ putStrLn list
しかし、まだHaskellを学習しているように思えるので、CesarBが書いたことを理解することが重要です。