Skip to content

Instantly share code, notes, and snippets.

@Thorium
Created February 21, 2013 01:21
Show Gist options
  • Save Thorium/5001162 to your computer and use it in GitHub Desktop.
Save Thorium/5001162 to your computer and use it in GitHub Desktop.
Agent that can upgrade its functionality on the fly. (F# MailboxProcessor containing function in the loop...)
// Erlang-style message-passing:
// Agent that can upgrade its functionality on the fly.
// Note: static typing, this agent can't upgrade its state data type (so better to use obj or custom interface)...
// Also this runs only in localhost...
// So this is more a technical demo than something useful
open System
type Methods<'state, 'x, 'reply> =
| Upgrade of
('x*'state -> 'x*'state) // function what to do
*('state -> 'state) // just for state conversion
| From of AsyncReplyChannel<'reply> * 'x
type UpgradableAgent<'state, 'x>() =
let gen_server = MailboxProcessor.Start(fun msg ->
let rec loop (state, f) =
async {
let! receive = msg.Receive()
match receive with
| Upgrade(f1,f2) ->
let state1 = f2(state)
return! loop(state1, f1)
| From(from, x) ->
let (reply, state1) = f(x,state)
from.Reply(reply)
return! loop(state1, f)
}
let initDoit (x,state) = (x, state)
let initState = Unchecked.defaultof<'state> //None
loop(initState, initDoit))
member this.DoIt (item:'x) =
// could use also PostAndAsyncReply
gen_server.PostAndReply(fun rep -> From(rep, item))
member this.Upgrade functionality =
functionality |> Upgrade |> gen_server.Post
let test1 =
let server = new UpgradableAgent<int, int>()
let myfunc = fun (x,state) -> (x+state, state)
let myStateConvert = fun initstate -> 5
server.Upgrade(myfunc, myStateConvert)
Console.WriteLine(server.DoIt(7)); // 12
Console.WriteLine(server.DoIt(7)); // 12
let myfunc2 = fun (x,state) -> (x+state, x+state)
let myStateConvert2 = fun initstate -> 5
server.Upgrade(myfunc2, myStateConvert2)
Console.WriteLine(server.DoIt(7)); // 12
Console.WriteLine(server.DoIt(7)); // 19
Console.WriteLine(server.DoIt(7)); // 26
let test3 =
let server3 = new UpgradableAgent<obj, string>()
let myfunc3 ((x:string), (state:obj)) = (x+unbox(state), box(x+unbox(state)))
let myStateConvert3 = fun initstate -> box(" world!")
server3.Upgrade(myfunc3, myStateConvert3)
Console.WriteLine(server3.DoIt("hello")); // "hello world!"
Console.WriteLine(server3.DoIt("hello ")); // "hello hello world!"
@Thorium
Copy link
Author

Thorium commented Feb 21, 2013

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment