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)))