pub fn run_child<'a, Input, Output, ChildInput, ChildOutput, OnInput, OnOutput, Result>(
    on_input: OnInput,
    on_output: OnOutput,
    child: Coroutine<'a, ChildInput, ChildOutput, Result>
) -> Coroutine<'a, Input, Output, Result>where
    OnInput: Fn() -> Coroutine<'a, Input, Output, ChildInput> + 'a,
    OnOutput: Fn(ChildOutput) -> Coroutine<'a, Input, Output, ()> + 'a,
Expand description

Runs a subroutine and converts it to the hosted type

As the child subroutine may have different inputs and outputs you need to specify how to convert between these worlds. This is done by providing functions that yield coroutines that can be ran in the ‘parent’ context. One that is ran whenever the child needs an input and one that is ran when the child produces an output

These can simply proxy through to the parents context, or perform more processing. Both still retain inputs and outputs so they may call a parents recieve multiple times

use bicoro::*;

/* Types in this example are written explicitly to highlight what they are
   It should be possible to use more compact forms
*/

// Reads a value, echos it, then returns 0u8
let child: Coroutine<i64,i64,u8> = receive().and_then(send).and_then(|()| result(0u8));

// an example where we require two inputs from the parent context, to one on the child
// in this case we add the two i32's together to form an i64
let on_input = | | -> Coroutine<i32,_,i64> {
    bind(receive(),|a| {
        map(receive(),move |b| {
            (a as i64+b as i64)
        })
    })
};

// parent expects strings on it's output channel so we convert
// note: type gaps used here as it must line up with the parent context types
// also means it's possible to read from the parent context when producing output
let on_output = | o:i64 | -> Coroutine<_,String,()> {
    send(o.to_string())
};

// run_child maps the child routine into the parenst 'world'
// we can see the type of this is the parent coroutine
let parent : Coroutine<i32,String,u8> = run_child(on_input,on_output,child);