我如何解析Haskell中的整数矩阵? [英] How do I parse a matrix of integers in Haskell?
问题描述
以下是输入文件的外观:
mn
k1,k2 ...
a11,....,an
a21,.... a22
...
am1 ... amn
其中m,n只是整数, K = [k1,k2 ...]
是一个整数列表, a11..amn
是一个矩阵(a列表): A = [[a11,... a1n],... [am1 ... amn]]
以下是我的快速Python版本:
$ b
def parse(filename):
形式输入:
mn
k1,k2 ...
a11,...,an
a21,... a22
...
am1 ... amn
f =打开(文件名)
(m,n)= f.readline()。split()
m = int(m)
n = int(n)
K = [int(k)for k in f.readline()。split()]
#Matri x - 列表列表
A = []
在范围内(m):
row = [float(el)for f.readline()。split()]
A.append(row)
return(m,n,K,A)
以下是我在Haskell中得到的(不是很强):
import System.Environment
import Data.List
main = do
(fname:_)< - getArgs
putStrLn fname - 由于putStrLn进入IO()monad,我们不能只应用它
解析< - 解析fname
putStrLn解析
解析fname =执行
内容< - readFile fname
- ,,,缺少东西......我怎么能得到第一个元素,并在其上匹配?
返回内容
我对单子(以及上下文陷入我的陷阱!)和do语句。我真的想写这样的东西,但我知道这是错的:
firstLine< - contents.head
(m,n)< - map read(words firstLine)
因为内容不是列表 - 但是一个monad。
对 next 步骤的任何帮助都会很棒。
liftM行。 readFile
获取文件中的行列表。然而,这个例子仍然只是转换了ENTIRE文件,并没有使用第一行或第二行......
非常简单的版本可能是:
$ p $ import Control.Monad(liftM)
- - 这纯粹运行在字符串
列表上,并且当传递的东西不是
时 - 匹配模式
parse_lines :: [String] - > (Int,Int,[Int],[[Int]])
parse_lines(mn_line:ks_line:matrix_lines)=(m,n,ks,matrix)
其中[m,n] = read_ints mn_line
ks = read_ints ks_line
matrix = parse_matrix matrix_lines
- 这里是循环剩余行以形成矩阵
parse_matrix :: [String] - > ; [[Int]]
parse_matrix lines = parse_matrix'lines []
其中parse_matrix'[] acc =反向acc
parse_matrix'(l:ls)acc = parse_matrix'ls $(read_ints l ):acc
- 这里给出读取
的正确签名read_ints :: String - > [Int]
read_ints =地图读取。单词
- 读取文件内容并将结果提取到IO
parse_file :: FilePath - > IO(Int,Int,[Int],[[Int]])
parse_file filename = do
file_lines< - (liftM lines。readFile)filename
return $ parse_lines file_lines
您可能希望查看Parsec进行更好的解析,并提供更好的错误处理功能。
* Main Control.Monad> parse_filetest.txt
(3,3,[1,2,3],[[1,2,3],[4,5,6],[7,8,9]])
So I've read the theory, now trying to parse a file in Haskell - but am not getting anywhere. This is just so weird...
Here is how my input file looks:
m n
k1, k2...
a11, ...., an
a21,.... a22
...
am1... amn
Where m,n are just intergers, K = [k1, k2...]
is a list of integers, and a11..amn
is a "matrix" (a list of lists): A=[[a11,...a1n], ... [am1... amn]]
Here is my quick python version:
def parse(filename):
"""
Input of the form:
m n
k1, k2...
a11, ...., an
a21,.... a22
...
am1... amn
"""
f = open(filename)
(m,n) = f.readline().split()
m = int(m)
n = int(n)
K = [int(k) for k in f.readline().split()]
# Matrix - list of lists
A = []
for i in range(m):
row = [float(el) for el in f.readline().split()]
A.append(row)
return (m, n, K, A)
And here is how (not very) far I got in Haskell:
import System.Environment
import Data.List
main = do
(fname:_) <- getArgs
putStrLn fname --since putStrLn goes to IO ()monad we can't just apply it
parsed <- parse fname
putStrLn parsed
parse fname = do
contents <- readFile fname
-- ,,,missing stuff... ??? how can I get first "element" and match on it?
return contents
I am getting confused by monads (and the context that the trap me into!), and the do statement. I really want to write something like this, but I know it's wrong:
firstLine <- contents.head
(m,n) <- map read (words firstLine)
because contents is not a list - but a monad.
Any help on the next step would be great.
So I've just discovered that you can do:
liftM lines . readFile
to get a list of lines from a file. However, still the example only only transforms the ENTIRE file, and doesn't use just the first, or the second lines...
The very simple version could be:
import Control.Monad (liftM)
-- this operates purely on list of strings
-- and also will fail horribly when passed something that doesn't
-- match the pattern
parse_lines :: [String] -> (Int, Int, [Int], [[Int]])
parse_lines (mn_line : ks_line : matrix_lines) = (m, n, ks, matrix)
where [m, n] = read_ints mn_line
ks = read_ints ks_line
matrix = parse_matrix matrix_lines
-- this here is to loop through remaining lines to form a matrix
parse_matrix :: [String] -> [[Int]]
parse_matrix lines = parse_matrix' lines []
where parse_matrix' [] acc = reverse acc
parse_matrix' (l : ls) acc = parse_matrix' ls $ (read_ints l) : acc
-- this here is to give proper signature for read
read_ints :: String -> [Int]
read_ints = map read . words
-- this reads the file contents and lifts the result into IO
parse_file :: FilePath -> IO (Int, Int, [Int], [[Int]])
parse_file filename = do
file_lines <- (liftM lines . readFile) filename
return $ parse_lines file_lines
You might want to look into Parsec for fancier parsing, with better error handling.
*Main Control.Monad> parse_file "test.txt"
(3,3,[1,2,3],[[1,2,3],[4,5,6],[7,8,9]])
这篇关于我如何解析Haskell中的整数矩阵?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!