Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F# 递归计算表达式_F#_Tail Recursion_Stack Overflow_Computation Expression - Fatal编程技术网

F# 递归计算表达式

F# 递归计算表达式,f#,tail-recursion,stack-overflow,computation-expression,F#,Tail Recursion,Stack Overflow,Computation Expression,在一个例子中,我被告知如何重写我的计算表达式,以便它使用尾部递归。我重写了代码,但仍然得到了StackOverflowException。为了找出问题所在,我使用状态monad编写了一些小代码(摘自): type State=状态('s->'a*'s) 让runState(State s)initialState=s initialState 让getState=State(funs->(s,s)) 设putState s=State(fun->((),s)) 类型StateBuilder()=

在一个例子中,我被告知如何重写我的计算表达式,以便它使用尾部递归。我重写了代码,但仍然得到了StackOverflowException。为了找出问题所在,我使用状态monad编写了一些小代码(摘自):

type State=状态('s->'a*'s)
让runState(State s)initialState=s initialState
让getState=State(funs->(s,s))
设putState s=State(fun->((),s))
类型StateBuilder()=
成员this.returna=状态(funs->(a,s))
这个成员。绑定(m,k)=
状态(fun s->let(a,s')=运行状态(ka)s′中的运行状态ms)
成员this.ReturnFrom a=a
let state=new StateBuilder()
设s max=
让rec循环acc=状态{
让!n=getState
do!putState(n+1)
如果acc<最大值,则
返回!循环(acc+1)
否则返回acc
}
循环0
运行状态(s 100000)0
这是再次抛出StackOverflowException,尽管循环函数可以使用尾部递归(?)。我猜StateBuilder类有问题。我试着用延迟法做些什么。在一个额外的lambda中包装所有东西,但没有成功。 我现在完全累坏了。这里是我的第二次尝试(未编译):

type State=状态('s->'a*'s)
让runState(State s)initialState=s initialState
让getState=fun()->State(funs->(s,s))
让putState s=fun()->State(fun->((),s))
类型StateBuilder()=
成员this.Delay(f)=fun()->f()
成员this.returna=状态(funs->(a,s))
这个成员。绑定(m,k)=
fun()->State(fun s->let(a,s')=运行状态中的运行状态(m())s((ka())s'))
成员this.ReturnFrom a=a
let state=new StateBuilder()
设s max=
让rec循环acc=状态{
让!n=getState
do!putState(n+1-acc)
如果acc<最大值,则
返回!循环(acc+2)
否则返回acc
}
循环0
运行状态(s 100000())0

我担心您可能会收到
StackOverflowException
,因为您正在调试模式下运行程序,并且禁用了尾部调用生成。如果转到“项目属性”,则可以在“生成”选项卡上找到“生成尾部调用”复选框。当我创建一个新项目时,我可以复制该行为,但选中此选项后,它工作正常(即使迭代次数要大得多)

默认情况下,在调试模式下禁用尾部调用的原因是,这会使调试更加困难(如果调用作为尾部调用执行,则在调用堆栈窗口中不会看到它)


这将是一个相当愚蠢的错误原因。。。很抱歉,你刚才问我的时候我忘了提这个

很简单,当你真的知道的时候:D谢谢你!现在它正在工作。
type State<'a, 's> = State of ('s -> 'a * 's)

let runState (State s) initialState = s initialState

let getState = State (fun s -> (s,s))
let putState s = State (fun _ -> ((),s))

type StateBuilder() =
  member this.Return a = State (fun s -> (a, s))
  member this.Bind(m, k) = 
    State (fun s -> let (a,s') = runState m s in runState (k a) s')
  member this.ReturnFrom a = a
let state = new StateBuilder()

let s max = 
    let rec Loop acc = state {
        let! n = getState
        do! putState (n + 1)
        if acc < max then
            return! Loop (acc + 1)
        else return acc
        }
    Loop 0

runState (s 100000) 0
type State<'a, 's> = State of ('s -> 'a * 's)

let runState (State s) initialState = s initialState

let getState = fun () -> State (fun s -> (s,s))
let putState s = fun () -> State (fun _ -> ((),s))

type StateBuilder() =
  member this.Delay(f) = fun () -> f()
  member this.Return a = State (fun s -> (a, s))
  member this.Bind(m, k) = 
    fun () -> State (fun s -> let (a,s') = runState (m ()) s in runState ((k a) ()) s')
  member this.ReturnFrom a = a
let state = new StateBuilder()

let s max = 
    let rec Loop acc = state {
        let! n = getState
        do! putState (n + 1 - acc)
        if acc < max then
            return! Loop (acc + 2)
        else return acc
        }
    Loop 0

runState (s 100000 ()) 0