Вторая переменная должна быть добавлена в определение типа задачи, чтобы выразить отдельные значения успеха и ошибки.Вот полное решение:
type (_,_) task =
| Success : 'a -> ('a,_) task
| Fail : 'x -> (_,'x) task
| Binding : ((('a,'x) task -> unit) -> unit) -> ('a,'x) task
| AndThen : ('a -> ('b,'x) task) * ('a,'x) task -> ('b,'x) task
| OnError : ('x -> ('a,'y) task) * ('a,'x) task -> ('a,'y) task
type (_,_) stack =
| NoStack : (_,_) stack
| AndThenStack : ('a -> ('b,'x) task) * ('b,'x) stack -> ('a,'x) stack
| OnErrorStack : ('x -> ('a,'y) task) * ('a,'y) stack -> ('a,'x) stack
type ('a,'x) process =
{ root: ('a,'x) task
; stack: ('a,'x) stack
}
let rec loop : type a x. (a, x) process -> unit = fun proc ->
match proc.root with
| Success value ->
let rec step : 'x. (a, 'x) stack -> unit = function
| NoStack -> ()
| AndThenStack (callback, rest) -> loop {root = callback value; stack = rest }
| OnErrorStack (_callback, rest) -> step rest
in
step proc.stack
| Fail value ->
let rec step : 'a. ('a, x) stack -> unit = function
| NoStack -> ()
| AndThenStack (_callback, rest) -> step rest
| OnErrorStack (callback, rest) -> loop {root = callback value; stack = rest }
in
step proc.stack
| Binding callback -> callback (fun task -> loop {proc with root = task})
| AndThen (callback, task) -> loop {root = task; stack = AndThenStack (callback, proc.stack)}
| OnError (callback, task) -> loop {root = task; stack = OnErrorStack (callback, proc.stack)}