Я пытаюсь понять, как вызывать правильные рекурсивные функции в вычислительных выражениях и не получать исключение переполнения стека. Насколько я понимаю, это довольно известная проблема, но до сих пор не может понять концепцию. Может быть, у кого-то есть простые объяснения или примеры для этого.F # рекурсивное связывание в вычислительных выражениях и хвостовой рекурсивности
Вот мой пример я хочу проследить строитель есть поведение, аналогичное seq
но не работает с SEQ монады вместо с каким-то другим, например option
и возвращать только последние ненулевого значения None из рекурсивного цикла. Является ли это возможным ?
Это просто пример, код будет работать бесконечно, но там не должно быть stackowerflow исключение
Как я понимаю, проблема с переполнением стека в Объединить метод, код просто держать вызова функции f() в рекурсивном цикле, и я хочу, чтобы избежать этого и сделать этот хвост хвоста хвоста, то есть код должен быть скомпилирован в регулярном цикле.
type TraceBuilder() =
member __.Bind (m: int Option, f: int -> int Option) : int Option =
match m with
| Some(v) -> f v
| None -> None
member this.Yield(x) = Some x
member this.YieldFrom(x) = x
member __.Delay(f) = f
member __.Run(f) = f()
member __.Combine (a, f) =
match a with
| Some _ -> a
| None -> f()
let trace = new TraceBuilder()
let rec iterRec (xopt: int Option) =
trace {
yield! None
let! x = xopt
yield! iterRec(Some(x + 1))
}
[<EntryPoint>]
let main argv =
let x = iterRec(Some(0))
//x = startFrom(0) |> Seq.take(5000) |> Seq.toList |> ignore
printfn "%A" x
Мышление кода в соц. Выражение должно компилируется
let iterRec xopt =
combine (None, (fun() ->
bind(xopt, fun x -> iterRec(Some(x+ 1)))
И похоже, в этом случае iterRec вызова не хвостовая рекурсия, так почему, Что stackoveflow, можно реализовать эту логику хвостовая рекурсия?
Прочитайте эти ссылки, до сих пор не могу понять решение:
(How) can I make this monadic bind tail-recursive?
Вот предложение, как решить проблему с помощью FsControl LIB, но это можно решить проблему с помощью регулярных выражений вычислений?
Recursive functions in computation expressions
Avoiding stack overflow (with F# infinite sequences of sequences)
https://fsharpforfunandprofit.com/posts/computation-expressions-builder-part5/
Вызов 'f()' '' Combine' уже является хвостовым рекурсивным. Не совсем понятно, в чем проблема. Возможно, это поможет, если вы сможете построить меньший пример. –
У меня есть фрагмент кода кода, который можно скомпилировать. – baio
Все еще неясно, с какими проблемами вы сталкиваетесь. –