1

我有包含这样数据的文本文件:

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

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

4

3 回答 3

4

是的,它被称为read

let i = read "13" :: Integer
let ts = read "[(1,2),(2,3),(4,5)]" :: [(Integer, Integer)]
于 2013-05-29T11:27:33.453 回答
2

您提供的示例文本文件包含尾随空格和句号,因此仅剪切最后一个字符是行不通的。让我们只取数字,使用:

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)

read函数适用于任何具有 Read 实例的数据类型,并自动生成正确类型的数据。

> getMyStuff "data.txt" >>= print
MyStuff {firstNum = 13, secondNum = 13, intPairList = [(1,2),(2,3),(4,5)]}

更好的方法

我倾向于为自己节省一些工作,直接写数据,所以

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

readMyStuff :: FilePath -> IO MyStuff
readMyStuff filename = fmap read (readFile filename)

fmap只是将纯函数read应用于 的输出readFile。)

> writeMyStuff "test.txt" MyStuff {firstNum=12,secondNum=42, intPairList=[(1,2),(3,4)]}
> readMyStuff "test.txt" >>= print
MyStuff {firstNum = 12, secondNum = 42, intPairList = [(1,2),(3,4)]}

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

于 2013-05-29T11:47:59.213 回答
2

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

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

于 2013-05-29T11:32:14.763 回答