1

在 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() 添加到构建器?任何想法如何正确地做到这一点?代码示例?

4

1 回答 1

5

假设spaceis的返回类型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.

于 2013-11-20T21:24:21.073 回答