在Haskell中,我可以这样写:
token: Parser a -> Parser a
token p = do space
v <- p
space
return v
在 F# 中,我已经走到了这一步:
let token = compose {
let! _ = space
let! v = parser
let! _ = space
return v
}
换句话说,我必须引入这个未使用的let! _ =
绑定来丢弃我不需要的"空间"解析器(monad(的解析值。
如何避免F#中这些无用的绑定?我尝试使用 do!,但出现错误(因为我的 >>=
函数不接受类型单位,而是采用"a"(:
let (>>=) (p: Parser<'a>) (f: 'a -> Parser<'b>) : Parser<'b>
这是我的构建器定义:
type ParserComposer() =
member x.Bind(p, f) = p >>= f
member x.Return(y) = ret y
member x.Zero() = failure
我需要定义>>
函数吗?将 Combine(( 添加到构建器?任何想法如何做到这一点?代码示例?
假设space
的返回类型是Parser<unit>
(如果它不表示返回某些结果的解析器,这将是有意义的(,您可以编写:
let token = compose {
do! space
let! v = parser
do! space
return v
}
这只是您编写的内容的语法糖 - 因此do! e
被翻译为let! _ = e
,而又被翻译成parser.Bind(e, fun _ -> ...)
。我有一个关于 Try Joinads 的加法解析器示例,它还定义了Combine
和更多(可能(有用的东西,但 do!
关键字只需要Bind
。