Чтение из входных файлов в haskell - PullRequest
1 голос
/ 17 марта 2012

Я решаю Проект Эйлера Задача 11 . Я скопировал в таблицу проблему в файл с именем «input.txt». Каждая строка входного файла содержит строку матрицы 20x20, а столбцы разделены пробелами.

Мне нужна функция, которая читает этот файл и возвращает его в виде массива ввода-вывода. У меня огромные проблемы с этим.

Пока я сделал это:

import System.IO
import Control.Monad

main = readFile "input.txt"

Это, конечно, только дает мне IO String представление входного файла, но все, что я пытаюсь, кажется, терпит неудачу. Как мне поступить? Я знаю, что должен сделать что-то вроде

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

но преобразование чисел для меня совершенно невозможно, скорее всего потому, что я еще не до конца понимаю монады.

Я уверен, что это на самом деле довольно легко, если вы поймете это.

У кого-нибудь есть предложения о том, что делать?

Ответы [ 2 ]

5 голосов
/ 17 марта 2012

Вы можете проанализировать ваш файл примерно так:

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

Комбинируя words с map read (где read :: (Read a) => String -> a), вы получаете список [Int].

Итак, чтобы немного упорядочить вещи, ваш код в монаде ввода-вывода может выглядеть следующим образом (при условии, что каждая строка имеет одинаковое фиксированное число столбцов и что вы берете имя входного файла, количество строк и столбцов в качестве аргументов командной строки):

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] при условии, что Read a, так что мы не ограничиваемся только целыми числами. Функция liftM берет чистую функцию (нашу readWords) и «поднимает» ее для работы в текущей монаде, т.е. IO.

0 голосов
/ 17 марта 2012

Вся программа должна выглядеть следующим образом:

import System.IO
import Data.Array

main = do
    content <- readFile "input.txt"
    let matrix = map (map read . words) $ lines content     -- [[Int]]
    let arr = listArray ((1, 1), (20, 20)) (concat matrix)
    putStr $ solve arr

Где solve - это функция типа Array (Int, Int) Int -> String.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...