我正在尝试将有关 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/