从哈斯克尔输入文件读取 [英] Reading from input files in haskell

查看:89
本文介绍了从哈斯克尔输入文件读取的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我解决项目欧拉问题11 。我已经复制粘贴表中的问题转化为一个名为input.txt的文件。输入文件的每一行都包含一个20×20矩阵的行和列由空格分隔。

I am solving Project Euler Problem 11. I have copy-pasted the table in the problem into a file called "input.txt". Each line of the input file contains a row of a 20x20 matrix, and the columns are separated by whitespace.

我要的是读取这个文件,并将其作为一个IO阵列功能。我有巨大的麻烦这样做。

What I want is a function that reads this file, and returns it as an IO Array. I'm having huge trouble doing this.

到目前为止,我已经做到了这一点:

So far I've done this:

import System.IO
import Control.Monad

main = readFile "input.txt"

这当然只是给我的输入文件的IO字符串重新presentation,但一切我尝试似乎失败。我应该如何进行?我知道我应该做这样的事情。

This of course only gives me the IO String representation of the input file, but everything I try seems to fail. How should I proceed? I know I should do something like

array ((1,1),(20,20)) [ the numbers tupled with their indices ]

但转换的数字对我来说是完全不可能,很可能是因为我并不完全了解单子呢。

but converting the numbers is outright impossible for me, most likely because I do not entirely understand monads yet.

我相信,其实这是很容易的,一旦你了解它。

I am confident that this is in fact quite easy, once you understand it.

是否有人在做什么建议吗?

Does anyone have a suggestion about what to do?

推荐答案

您可以用这样的分析文件:

You can parse your file with something like this:

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)]

通过结合地图阅读(其中 ::阅读(阅读) = GT;弦乐 - >将),你会得到一个List [INT]

By combining words with map read (where read :: (Read a) => String -> a) you get a list [Int].

所以,为了整理东西一点点,在IO单子您code可能看起来像这样(假设每一行都有列相同的固定数量以及所拍摄的输入文件名称,数量行并作为命令行参数列):

So, in order to organize things a little bit, your code in the IO monad may look like this (assuming that every row has the same fixed number of columns and that you take the input file name, the number of rows and of columns as commandline arguments):

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

请注意如何转换功能 readWords 能够转换为任何 [A] 提供的阅读,这样我们就不会限制自己仅整数。
liftM 函数接受一个纯函数(我们的 readWords )和升降机,它在当前的单子工作,即 IO

Note how the conversion function readWords is able to convert to any [a] provided that Read a, so that we don't restrict ourselves to integers only. The liftM function takes a pure function (our readWords) and "lifts" it to work in the current monad, i.e. IO.

这篇关于从哈斯克尔输入文件读取的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆