【发布时间】:2017-07-05 00:54:04
【问题描述】:
我目前正在做有关 Haskell 解析的作业,但我在一些基础知识方面遇到了困难。
作业: 我应该创建一个将字符串解析为三元组列表的函数。 以便: 甲、乙、丙 ,E,D
会导致
Triples [("A","B","C"), ("A","E","D")]
输入字符串将包含 ;\n 作为新三元组开始的指示。字符串将以点结尾。 三元组的元素可以是字母或数字或组合, 例如abc, a, 1, abc121.
因此,
"a,b,c;\n d,e;\n f,g;\n h,i."
会导致:
Triples [("a","b","c"),("a","d","e"),("a","f","g"),("a","h","i")]
我目前的解决方案:
parseTriplesD :: Parser Triples
parseTriplesD = parseTriples
>>= \rs -> return (Triples rs)
这个函数非常简单和正确。获取字符串并返回一个新类型 Triples 的对象,其中包含由 parseTriples 创建的 Triples 列表。
parseTriples :: Parser [Triple]
parseTriples = parseTriple
>>= \r -> ((string ";\n" >> parseTriples >>= \rs -> return (r:rs))
P.<|>(return[r]))
这个功能需要一些工作。我的想法是我使用另一个函数创建一个带有输入字符串的树元素的 Triple,忽略 /n 并递归调用它,同时将创建的三元组添加到返回列表中。当这不起作用时,因为它只能创建一个 Triple,它会返回一个包含 Triple 的列表。 我不知何故需要创建第一个三元组,然后使用这个三元组的第一个元素作为其他三元组的第一个元素。
问题 1 如何创建第一个三元组并将三元组的第一个元素用于其他三元组?
parseTriple :: Parser Triple
parseTriple = P.many (letter<|>digit) >>= \a -> P.char ','
>> P.many (letter<|>digit)>>= \b -> P.char ','
>> P.many (letter<|>digit)>>= \c -> return ((a,b,c))
这个函数很简单,但我不确定它是否正确。 我的想法是,它需要字符串的前几个字符(字母或数字),直到逗号 "," ,并将这些字符保存在 a 中。 重复 3 次,然后创建并返回一个包含三个元素的 Triple。
问题 2 如何只取字符串的几个字符(可以是字母或数字 EDIT: 或空格字符)直到逗号? P.many(字母数字)是否正确?
我们得到了什么:
Triples 数据结构:
newtype Triples = Triples [Triple] deriving (Show,Eq)
type Triple = (String, String, String)
进口:
import Test.HUnit (runTestTT,Test(TestLabel,TestList),(~?=))
import qualified Text.Parsec as P (char,runP,noneOf,many,(<|>),eof)
import Text.ParserCombinators.Parsec
import Text.Parsec.String
import Text.Parsec.Char
import Data.Maybe
测试用例
runParsec :: Parser a -> String -> Maybe a
runParsec parser input = case P.runP parser () "" input of
Left _ -> Nothing
Right a -> Just a
-- | Tests the implementations of 'parseScore'.
main :: IO ()
main = do
testresults <- runTestTT tests
print testresults
-- | List of tests for 'parseScore'.
tests :: Test
tests = TestLabel "parseScoreTest" (TestList [
runParsec parseTriplesD "0,1,2;\n2,3." ~?= Just (Triples [("0","1","2"),("0","2","3")]),
runParsec parseTriplesD "a,bcde ,23." ~?= Just (Triples [("a","bcde ","23")]),
runParsec parseTriplesD "a,b,c;\n d,e;\n f,g;\n h,i." ~?= Just (Triples [("a","b","c"),("a","d","e"),("a","f","g"),("a","h","i")]),
runParsec parseTriplesD "a,bcde23." ~?= Nothing,
runParsec parseTriplesD "a,b,c;d,e;f,g;h,i." ~?= Nothing,
runParsec parseTriplesD "a,b,c;\nd;\nf,g;\nh,i." ~?= Nothing
])
【问题讨论】:
-
您的第二个测试显示在
"bcde "的预期输出中捕获的空间。我以为你只想要输出中的字母数字字符。是错字吗? -
啊。错过了那个。我们没有得到直接的任务指示,只有测试用例。所以我认为它只是字母数字字符,但我完全错过了那个空格字符。我将在我的问题中对其进行编辑。
标签: parsing haskell functional-programming