Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Parsing Haskell:将reads函数提升到parsec解析器_Parsing_Haskell_Parsec - Fatal编程技术网

Parsing Haskell:将reads函数提升到parsec解析器

Parsing Haskell:将reads函数提升到parsec解析器,parsing,haskell,parsec,Parsing,Haskell,Parsec,作为第四个练习的一部分 我想将reads类型函数(如readHex)与parsec解析器一起使用 为此,我编写了一个函数: liftReadsToParse :: Parser String -> (String -> [(a, String)]) -> Parser a liftReadsToParse p f = p >>= \s -> if null (f s) then fail "No parse" else (return . fst . head

作为第四个练习的一部分 我想将
reads
类型函数(如
readHex
)与parsec
解析器一起使用

为此,我编写了一个函数:

liftReadsToParse :: Parser String -> (String -> [(a, String)]) -> Parser a
liftReadsToParse p f = p >>= \s -> if null (f s) then fail "No parse" else (return . fst . head ) (f s)
例如,可在GHCI中使用,如下所示:

*Main Numeric> parse (liftReadsToParse (many1 hexDigit) readHex) "" "a1"
Right 161
有人能就以下方面对该方法提出改进意见吗
  • 术语
    (fs)
    是否会被记忆,或者在
    null(fs)
    返回
    False
    的情况下评估两次?
  • 处理多个成功的解析,即当
    length(fs)
    大于1时,我不知道parsec如何处理这个问题。
  • 处理解析的剩余部分,即
    (snd.head)(fs)

    要回答问题的第一部分,不会记录任何
    (fs)
    ,您必须手动执行此操作:

    liftReadsToParse p f = p >>= \s -> let fs = f s in if null fs then fail "No parse"
                                                                  else (return . fst . head ) fs
    
    但我会使用模式匹配:

    liftReadsToParse p f = p >>= \s -> case f s of
                                            []              -> fail "No parse"
                                            (answer, _) : _ -> return answer
    

    这是个好主意。一个更自然的方法会使 您的
    读取
    解析器更适合使用Parsec 在类型的开头,不使用
    解析器字符串

    liftReadS :: ReadS a -> String -> Parser a
    liftReadS reader = maybe (unexpected "no parse") (return . fst) .
                       listToMaybe . filter (null . snd) . reader
    
    这种“combinator”风格是非常地道的Haskell-一旦你 习惯它,它使函数定义更容易 阅读和理解

    然后在简单的情况下使用
    liftReadS

    > parse (many1 hexDigit >>= liftReadS readHex) "" "a1"
    
    (请注意,
    listtomabe
    位于
    数据中。可能是
    模块。)

    在更复杂的情况下,
    liftReadS
    在任何应用程序中都很容易使用 Parsec
    do

    关于您的其他一些问题:

  • 功能
    读卡器
    现在只应用一次,因此没有什么可“记忆”的
  • 在大多数情况下,除了
    读取的
    解析器中的第一个解析之外,忽略所有解析都是一种常见且公认的做法,因此您很好

  • 非常好,我不知道为什么我不想传入
    字符串
    ,也感谢您提醒我有关
    maybe
    函数的信息。这似乎很相关: