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! _ =、不要な「スペース」パーサー (モナド) の解析値を破棄する必要があります。

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

spaceの戻り値の型がisであると仮定するとParser<unit>(結果を返すパーサーを表していない場合は意味があります)、次のように記述できます。

let token = compose {
    do! space
    let! v = parser
    do! space
    return v
}

これは、あなたが書いたものの構文糖衣にすぎdo! eませlet! _ = eparser.Bind(e, fun _ -> ...)Try Joinadsに Additive パーサーのサンプルがあり、さらにいくつかの (おそらく) 便利なものも定義されていますCombineが、do!キーワードに必要なのはBind.

于 2013-11-20T21:24:21.073 に答える