拆包嵌套的应用函子 f#

Unpacking nested applicative functors f#

你好我正在尝试制作一个组合器解析器,我目前正在尝试让它读取 headers 并根据解析的 header 创建解析器。即 header 的; int、float、string 将导致 Parser<Parser<int>*Parser<float>*Parser<string>>

不过我想知道您将如何解压缩 "inner" 解析器,然后得到类似的东西; Parser<int*float*string>?

解析器类型是:type Parser<'a> = Parser of (string -> Result<'a * string, string>)

我不确定您使用嵌套解析器的想法是否可行 - 如果您动态解析 header,那么您将需要生成相同类型的解析器列表。你写这个的方式暗示解析器的类型将取决于输入,这在 F# 中是不可能的。

因此,我希望您需要像这样定义一个值:

type Value = Int of int | String of string | Float of float

然后你解析 header 的解析器会产生类似这样的东西:

let parseHeaders args : Parser<Parser<Value> list> = (...)

下一个问题是,你想用嵌套解析器做什么?据推测,您需要将它们变成一个解析器来解析整行数据(如果这类似于 CSV 文件)。通常,您会定义一个函数 sequence:

val sequence : sep:Parser<unit> -> parsers:Parser<'a> list -> Parser<'a list>

这需要一个分隔符(例如,识别逗号的解析器)和一个解析器列表,并生成一个解析器,该解析器运行将所有解析器按序列排列,中间有分隔符。

那么你可以这样做:

parseHeaders input |> map (fun parsers -> sequence (char ',') parsers)

你得到一个解析器 Parser<Parser<string>>。您现在想要 运行 嵌套解析器位于 运行 识别 headers 的外部解析器之后剩下的部分。以下函数可以解决问题:

let unwrap (Parser f:Parser<Parser<'a>>) = Parser (fun s ->
  match f s with
  | Result.Ok(Parser nested, rest) -> nested rest 
  | Result.Error e -> Result.Error e )