Recursive Funktionen in Berechnungsausdrücken

Einigen Hintergrund zuerst. Ich lerne gerade ein paar Dinge über monadische Parser-Kombinatoren. Während ich versuchte, die 'chainl1'-Funktion von @ zu übertragdieses Papie (S. 16-17), ich habe diese Lösung gefunden:

let chainl1 p op = parser {
  let! x = p
  let rec chainl1' (acc : 'a) : Parser<'a> =
      let p' = parser {
          let! f = op
          let! y = p
          return! chainl1' (f acc y)
          }
      p' <|> succeed acc
  return! chainl1' x
}

Ich habe die Funktion mit einigen großen Eingaben getestet und eine StackOverflowException erhalten. Nun frage ich mich, ob es möglich ist, eine rekursive Funktion, die einen Berechnungsausdruck verwendet, so umzuschreiben, dass sie die Schwanzrekursion verwende

Wenn ich den Berechnungsausdruck erweitere, kann ich nicht sehen, wie es allgemein möglich wäre.

let chainl1 p op =
    let b = parser
    b.Bind(p, (fun x ->
    let rec chainl1' (acc : 'a) : Parser<'a> =
        let p' =
            let b = parser
            b.Bind(op, (fun f ->
            b.Bind(p, (fun y ->
            b.ReturnFrom(chainl1' (f acc y))))))
        p' <|> succeed acc
    b.ReturnFrom(chainl1' x)))

Antworten auf die Frage(4)

Ihre Antwort auf die Frage