我正在解决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.
一旦你理解了,我相信这实际上很容易.
有没有人有关于该做什么的建议?
您可以使用以下内容解析文件:
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.
| 归档时间: |
|
| 查看次数: |
2206 次 |
| 最近记录: |