Haskell 将数组字符串读入变量

Haskell 将数组字符串读入变量,haskell,Haskell,我有一个包含如下数据的文本文件: 13. 13. [(1,2),(2,3),(4,5)]. 我想把它读入Haskell的3个变量中。但是标准函数将其读取为字符串,但是考虑到我自己在最后去掉了点,是否有任何内置的解析器函数可以将整数“13”和[(整数,整数)]从[(1,2),(2,3),(4,5)]中列出?是的,它被称为read: let i = read "13" :: Integer let ts = read "[(1,2),(2,3),(4,5)]" :: [(Int

我有一个包含如下数据的文本文件:

13.    
13.      
[(1,2),(2,3),(4,5)].

我想把它读入Haskell的3个变量中。但是标准函数将其读取为字符串,但是考虑到我自己在最后去掉了点,是否有任何内置的解析器函数可以将整数“13”和
[(整数,整数)]
[(1,2),(2,3),(4,5)]
中列出?

是的,它被称为
read

let i = read "13" :: Integer
let ts = read "[(1,2),(2,3),(4,5)]" :: [(Integer, Integer)]

是的,它被称为
read

let i = read "13" :: Integer
let ts = read "[(1,2),(2,3),(4,5)]" :: [(Integer, Integer)]

哈斯凯尔的强势类型要求你知道自己得到了什么。因此,让我们放弃所有错误检查和优化,并假设文件始终采用正确的格式,您可以这样做:

data Entry = Number Integer
           | List [(Integer, Integer)]

parseYourFile :: FilePath -> IO [Entry]
parseYourFile p = do
  content <- readFile p
  return $ parseYourFormat content

parseYourFormat :: String -> [Entry]
parseYourFormat data = map parseEntry $ lines data

parseEntry :: String -> Entry
parseEntry line = if head line == '['
                  then List $ read core
                  else Number $ read core
    where core = init line
数据输入=数字整数
|列表[(整数,整数)]
parseYourFile::FilePath->IO[输入]
parseyourfilep=do
内容[条目]
parseYourFormat数据=映射parseEntry$行数据
parseEntry::String->Entry
parseEntry line=如果头行=='['
然后列出$readcore
else编号$read core
其中core=init行

或者,您可以使用众多combinator框架中的一种为其编写适当的解析器。

Haskell的强类型要求您了解得到的是什么。因此,让我们放弃所有错误检查和优化,假设文件始终采用正确的格式,您可以执行以下操作:

data Entry = Number Integer
           | List [(Integer, Integer)]

parseYourFile :: FilePath -> IO [Entry]
parseYourFile p = do
  content <- readFile p
  return $ parseYourFormat content

parseYourFormat :: String -> [Entry]
parseYourFormat data = map parseEntry $ lines data

parseEntry :: String -> Entry
parseEntry line = if head line == '['
                  then List $ read core
                  else Number $ read core
    where core = init line
数据输入=数字整数
|列表[(整数,整数)]
parseYourFile::FilePath->IO[输入]
parseyourfilep=do
内容[条目]
parseYourFormat数据=映射parseEntry$行数据
parseEntry::String->Entry
parseEntry line=如果头行=='['
然后列出$readcore
else编号$read core
其中core=init行

或者,您可以使用多种combinator框架中的一种为其编写一个合适的解析器。

您给出的示例文本文件有尾随空格和句号,因此仅剪切最后一个字符不起作用。让我们使用以下方法仅取数字:

import Data.Char (isDigit)
为什么不使用数据类型来存储文件中的内容:

data MyStuff = MyStuff {firstNum :: Int,
                        secondNum:: Int,
                        intPairList :: [(Integer, Integer)]}
    deriving (Show,Read)
现在我们需要读取文件,然后将其转换为单独的行:

getMyStuff :: FilePath -> IO MyStuff
getMyStuff filename = do
   rawdata <- readFile filename
   let [i1,i2,list] = lines rawdata
   return $ MyStuff  (read $ takeWhile isDigit i1)  (read $ takeWhile isDigit i2)  (read $ init list)
更好的方法 我倾向于为自己节省一些工作,直接写数据,所以

writeMyStuff :: FilePath -> MyStuff -> IO ()
writeMyStuff filename somedata = writeFile filename (show somedata)

readMyStuff :: FilePath -> IO MyStuff
readMyStuff filename = fmap read (readFile filename)
fmap
仅将纯函数
read
应用于
readFile
的输出)


如果让编译器为您整理所有内容,您的解析或打印错误可能会小得多,代码更少,也更简单。

您给出的示例文本文件有尾随空格和句号,因此仅剪切最后一个字符不起作用。让我们使用以下方法仅获取数字:

import Data.Char (isDigit)
为什么不使用数据类型来存储文件中的内容:

data MyStuff = MyStuff {firstNum :: Int,
                        secondNum:: Int,
                        intPairList :: [(Integer, Integer)]}
    deriving (Show,Read)
现在我们需要读取文件,然后将其转换为单独的行:

getMyStuff :: FilePath -> IO MyStuff
getMyStuff filename = do
   rawdata <- readFile filename
   let [i1,i2,list] = lines rawdata
   return $ MyStuff  (read $ takeWhile isDigit i1)  (read $ takeWhile isDigit i2)  (read $ init list)
更好的方法 我倾向于为自己节省一些工作,直接写数据,所以

writeMyStuff :: FilePath -> MyStuff -> IO ()
writeMyStuff filename somedata = writeFile filename (show somedata)

readMyStuff :: FilePath -> IO MyStuff
readMyStuff filename = fmap read (readFile filename)
fmap
仅将纯函数
read
应用于
readFile
的输出)


如果让编译器为您整理所有内容,那么您就不太可能出现小的解析或打印错误,代码更少,也更简单。

Prelude.read无解析错误。我有这样的代码:data EntryData=EntryData{height::Integer,width::Integer,entryList:[(Integer,Integer)]派生(显示、读取)getEntryData::FilePath->IO EntryData getEntryData文件名=do rawdata=打印字符串是否正确:(@user2349668我正在打电话,但是你确定文件中包含数据,然后是句点,然后是行的结尾吗?如果没有,map init将不会删除跟踪空格。用print而不是putStrLn测试它,以找出文件中还有哪些空白。Prelude.read无解析错误。我有这样的代码:data EntryData=EntryData{height::Integer,width::Integer,entryList::[(Integer,Integer)]}派生(显示,读取)getEntryData::FilePath->IO EntryData getEntryData filename=do rawdata=打印字符串正确:(@user2349668我现在在手机上,但是你确定文件中包含数据,然后是句点,然后是行的结尾吗?如果没有,map init将不会删除跟踪空格。请使用print而不是putStrLn对其进行测试,以找出文件中还有哪些空白。