Trong một số previous question Tôi được cho biết cách viết lại biểu thức tính toán của mình để nó sử dụng đệ quy đuôi. Tôi viết lại mã của tôi nhưng vẫn có một StackOverflowException. Để xác định vị trí các vấn đề tôi đã viết một số mã nhỏ sử dụng một đơn nguyên nhà nước (lấy từ this blog entry):Biểu thức tính toán đệ quy
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
này được ném một StackOverflowException một lần nữa, mặc dù chức năng Vòng có thể sử dụng đuôi đệ quy (?). Tôi đoán có điều gì đó sai với lớp StateBuilder. Tôi đã cố gắng làm điều gì đó với phương thức Delay. Bọc tất cả mọi thứ trong một lambda thêm, mà không thành công. Im hoàn toàn bị mắc kẹt vào lúc này. Dưới đây nỗ lực thứ hai của tôi (không biên dịch):
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
Thật dễ dàng, khi bạn thực sự biết điều đó: D Cảm ơn bạn! Bây giờ nó đang làm việc. – PetPaulsen