parsing - F# 解析器组合器

标签 parsing haskell f#

我正在尝试将有关 monadic 解析器( https://www.cs.nott.ac.uk/~gmh/pearl.pdf )的示例转换为 F#。

到目前为止,我有:

type Parser<'a> = Parser of  (string -> ('a*string) list)

let item : Parser<char> =
  Parser (fun (s:string) -> 
                match s with
                | "" -> []
                | null -> []
                | _ -> (s.Chars(0),s.Substring 1)::[])

let sat (pred : (char -> bool)) : Parser<char> =
  parserWf
    {
       let! c = item
       if pred c then return c
    }

let char c : Parser<char> =
  sat (fun c' -> c'.Equals(c))

let rec string (str:string) : Parser<string> =
  parserWf
    {
        if (str.Length > 0)
        then
            let! c = char (str.Chars 0)
            let! cs = string (str.Substring 1)
            printfn "String: %s" cs
            return c.ToString() + cs
        else
            return ""
    }

如果我删除 else return ""来自 string方法则结果始终是空列表。
在 Haskell 中声明了字符串函数:
string :: String -> Parser String
string "" = return ""
string (c:cs) = do {char c; string cs; return (c:cs)}  

这很好用。
为什么 F# 函数不能按预期工作?

最佳答案

我的 Haskell 有点生疏,但是您发布的代码段是否与您的 F# 代码等效,即在 Haskell 中,您也需要递归的基本情况(空字符串)?

如果删除 else 部分,对 string 的倒数第二个调用(即只剩下一个字符的那个)将不会从其递归调用(传递“”)中获得任何结果,因此它也不会返回任何有效结果。然后“向上”传播,你最终会得到一个空列表。

关于parsing - F# 解析器组合器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31108482/

相关文章:

php - 在 PHP 中使用命名空间解析 XML 数据

javascript - JS中解析JSON并比较键值

haskell - 使用 O(1) 函数编写 CString 的可存储实例以获取总字节长度

asynchronous - Hopac——只有在有人收听的情况下,我才能赋予 channel 值(value)吗?

android - 解析来自 Api 的响应 - 返回的数据被视为 double 和整数 - 如何解析

java - 解析特定类之前的某个标签的数据

haskell - QuantifiedConstraints 是如何翻译成字典传递风格的?

Haskell - 应用程序中的类型错误

linux - F# 代码在 REPL 中工作正常,但在编译期间出现堆栈溢出

f# - Ionide:如何指定 FSharpLint 的配置?