从haskell中的输入文件中读取

Und*_*ren 1 arrays io haskell

我正在解决Project Euler Problem 11.我已将问题中的表复制粘贴到名为"input.txt"的文件中.输入文件的每一行包含一行20x20矩阵,列由空格分隔.

我想要的是一个读取此文件的函数,并将其作为IO数组返回.我这样做很麻烦.

到目前为止我已经这样做了:

import System.IO
import Control.Monad

main = readFile "input.txt"
Run Code Online (Sandbox Code Playgroud)

这当然只给我输入文件的IO String表示,但我尝试的一切似乎都失败了.我该怎么办?我知道我应该做点什么

array ((1,1),(20,20)) [ the numbers tupled with their indices ]
Run Code Online (Sandbox Code Playgroud)

但转换这些数字对我来说是完全不可能的,很可能是因为我还没有完全理解monad.

一旦你理解了,我相信这实际上很容易.

有没有人有关于该做什么的建议?

Ric*_* T. 5

您可以使用以下内容解析文件:

s = "2 4\n6 8"

s' :: [Int]
s' = (map read . words) s

let arr = listArray ((1,1),(2,2)) s'
-- arr == array ((1,1),(2,2)) [((1,1),2),((1,2),4),((2,1),6),((2,2),8)]
Run Code Online (Sandbox Code Playgroud)

通过words与map read(where read :: (Read a) => String -> a)结合,您可以获得一个列表[Int].

因此,为了组织一些事情,IO monad中的代码可能看起来像这样(假设每行具有相同的固定列数,并且您将输入文件名,行数和列数视为命令行参数):

module Main

where

import Data.Array
import Control.Monad
import System.Environment

readWords :: (Read a) => String -> [a]
readWords = map read . words

parseFile :: String -> Int -> Int -> IO (Array (Int, Int) Int)
parseFile fname rows cols = do
    matr <- liftM readWords $ readFile fname
    return $ listArray ((1, 1), (rows, cols)) matr
    -- (matr :: [Int] is inferred from the parseFile's type)

main :: IO ()
main = do
    args <- getArgs
    case args of
        [fname, rows, cols] -> do
            arr <- parseFile fname (read rows) (read cols)
            print arr
Run Code Online (Sandbox Code Playgroud)

注意转换函数如何readWords能够转换为任何[a]提供的转换函数Read a,这样我们就不会仅限于整数.该liftM函数采用纯函数(我们的readWords)并"提升"它在当前monad中工作,即IO.