Hope the following may help
#light
namespace Common.Monads
type State<'state,'a> = State of ('state -> 'a * 'state)
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module State = begin
type StateBuilder =
class
new : unit -> StateBuilder
member Bind : m:State<'state,'a> * f:('a -> State<'state,'b>) -> State<'state,'b>
member BindUsing : m:State<'state,'a> * f:('a -> State<'state,'b>) ->State<'state,'b> when 'a :> System.IDisposable
member Combine : m1:State<'state,unit> * m2:State<'state,'a> -> State<'state,'a>
member Delay : f:(unit -> State<'state,'a>) -> State<'state,'a>
member For : s:#seq<'a> * f:('a -> State<unit,'b>) -> State<unit,unit>
//member Let : x:'a * f:('a -> 'b) -> 'b
member Return : x:'a -> State<'state,'a>
member TryFinally : m:State<'state,'a1> * f:(unit -> unit) -> State<'state,'a1>
member TryWith : m:State<'state,'a> * f:(exn -> State<'state,'a>) -> State<'state,'a>
member Using : x:'a * f:('a -> State<'state,'b>) -> State<'state,'b> when 'a :> System.IDisposable
member While : p:(unit -> bool) * m:State<unit,'a> -> State<unit,unit>
member Zero : unit -> State<'state,unit>
end
///[state {...}] is the [State] continuation builder.
val state : StateBuilder
///[Run m state] runs [m] with the [state] and returns the value and state.
val Run : State<'state,'a> -> 'state -> 'a * 'state
///[GetState] is a continuation returning the current state of the continuation.
///Example of use : [state { let! state = get ... }]
val GetState : State<'state,'state>
///[SetState newState] is a continuation putting [newState] as the new state of the continuation.
///Example of use : [state { do! put newState }]
val SetState : 'state -> State<'state,unit>
///[MapState f] is a continuation putting [f oldState] as the new state of the continuation.
///Example of use : [state { do! modify (fun oldState -> oldState) }]
val MapState : ('state -> 'state) -> State<'state,unit>
///[Eval m s] returns the state of [m] at the end of the continuation computation
///which has used [s] as its initial state.
val Eval : State<'state,'a> -> 'state -> 'state
///[Exec m s] returns the value of [m] at the end of the continuation computation
///which has used [s] as its initial state.
val Exec : State<'state,'a> -> 'state -> 'a
///[MapStateAndResult f m] returns a new [State] continuation by applying [f value state] where
///[value] and [state] are the value and state of [m].
val MapStateAndResult : ('a -> 'state -> 'b * 'state) -> State<'state,'a> -> State<'state,'b>
end
//=======================================
#light
namespace Common.Monads
open System
type State<'state, 'a> = State of ('state ->'a * 'state)
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
module State =
let private succeed x = State (fun s -> x, s)
let Run (State f) s = f s
let private bind m f =
State (fun s ->
let v, s = Run m s
Run (f v) s
)
let private delay f = State (fun s -> Run (f()) s)
let private try_with m f = State (fun s -> try Run m s with e -> Run (f e) s)
let private try_finally m f = State (fun s -> try Run m s finally f())
let private dispose (x: #IDisposable) = x.Dispose()
let private using r f = try_finally (f r) (fun () -> dispose r)
let rec private do_while p m =
if p() then
bind m (fun _ -> do_while p m)
else
succeed ()
type StateBuilder () =
member b.Bind(m, f) = bind m f
member b.BindUsing(m, f) = bind m (fun r -> using r f)
member b.Combine(m1, m2) = bind m1 (fun () -> m2)
member b.Delay(f) = delay f
member b.For(s:#seq<_>, f:('a->State<unit, 'b>)) =
using (s.GetEnumerator()) (fun ie ->
do_while (fun () -> ie.MoveNext()) (delay (fun() -> f ie.Current))
)
// member b.Let(x, f) = f x
member b.Return(x) = succeed x
member b.TryFinally (m, f) = try_finally m f
member b.TryWith(m, f) = try_with m f
member b.Using(x : #IDisposable, f) = try_finally (f x) (fun () -> x.Dispose())
member b.While(p, m:State<unit, 'a>) = do_while p m
member b.Zero() = succeed ()
let state = StateBuilder()
let GetState = State (fun s -> s, s)
let SetState s = State (fun _ -> (), s)
let MapState f =
State (fun s ->(), f s)
let Eval m s =
let _, s = Run m s
s
let Exec m s =
let v, _ = Run m s
v
let MapStateAndResult f m =
State (fun s ->
let v, s = Run m s
let v', s' = f v s
Run (succeed v') s'
)
//Example
#r "FSharp.PowerPack.dll"
open State
//State<int, int>
let test =
state
{ let! x = GetState
let y = 100
do! SetState (x + y * 100)
return x
}
let _ =
let seed = 100
System.Console.WriteLine("seed:{0}", seed)
System.Console.WriteLine("test : Run:{0}", Run test seed)
System.Console.WriteLine("test : value:{0} \t state:{1}", Exec test seed, Eval test seed)
//State<foo, int>
//with type foo = {a : int ; mutable b :int }
type foo = {a : int ; mutable b :int }
let test =
state
{ let! x = GetState
print_endline ("pre " + any_to_string x)
do! MapState (fun x -> {x with a = 700})
let! x = GetState
print_endline ("post " + any_to_string x)
let! x = GetState
return ()
}
let _ = Run test {a = 0; b = 0}
Thanks a lot, much appreciated!
I guess I was thinking of having the get/put as members on the builder, but of course the little GetState and MapState combinators do the trick nicely.
I guess I was thinking of having the get/put as members on the builder, but of course the little GetState and MapState combinators do the trick nicely.
Topic tags
- f# × 3660
- compiler × 263
- functional × 199
- c# × 119
- websharper × 114
- classes × 96
- web × 94
- book × 84
- .net × 82
- async × 72
- parallel × 43
- server × 43
- parsing × 41
- testing × 41
- asynchronous × 30
- monad × 28
- ocaml × 26
- tutorial × 26
- haskell × 25
- workflows × 22
- html × 21
- linq × 21
- introduction × 19
- silverlight × 19
- wpf × 19
- fpish × 18
- collections × 14
- pipeline × 14
- templates × 12
- monads × 11
- opinion × 10
- reactive × 10
- plugin × 9
- scheme × 9
- sitelets × 9
- solid × 9
- basics × 8
- concurrent × 8
- deployment × 8
- how-to × 8
- python × 8
- complexity × 7
- javascript × 6
- jquery × 6
- lisp × 6
- real-world × 6
- workshop × 6
- xaml × 6
- conference × 5
- dsl × 5
- java × 5
- metaprogramming × 5
- ml × 5
- scala × 5
- visual studio × 5
- formlets × 4
- fsi × 4
- lift × 4
- sql × 4
- teaching × 4
- alt.net × 3
- aml × 3
- enhancement × 3
- list × 3
- reflection × 3
- blog × 2
- compilation × 2
- computation expressions × 2
- corporate × 2
- courses × 2
- cufp × 2
- enterprise × 2
- entity framework × 2
- erlang × 2
- events × 2
- f# interactive × 2
- fsc × 2
- google maps × 2
- html5 × 2
- http × 2
- interactive × 2
- interface × 2
- iphone × 2
- iteratee × 2
- jobs × 2
- keynote × 2
- mvc × 2
- numeric × 2
- obfuscation × 2
- oop × 2
- packaging × 2
- pattern matching × 2
- pipelines × 2
- rx × 2
- script × 2
- seq × 2
- sockets × 2
- stm × 2
- tcp × 2
- trie × 2
- type × 2
- type provider × 2
- xna × 2
- zh × 2
- .net interop × 1
- 2012 × 1
- abstract class × 1
- accumulator × 1
- active pattern × 1
- addin × 1
- agents × 1
- agile × 1
- android × 1
- anonymous object × 1
- appcelerator × 1
- architecture × 1
- array × 1
- arrays × 1
- asp.net 4.5 × 1
- asp.net mvc × 1
- asp.net mvc 4 × 1
- asp.net web api × 1
- aspnet × 1
- ast × 1
- b-tree × 1
- bistro × 1
- bug × 1
- camtasia studio × 1
- canvas × 1
- class × 1
- client × 1
- clojure × 1
- closures × 1
- cloud × 1
- cms × 1
- coding diacritics × 1
- color highlighting × 1
- combinator × 1
- confirm × 1
- constructor × 1
- continuation-passing style × 1
- coords × 1
- coursera × 1
- csla × 1
- css × 1
- data × 1
- database × 1
- declarative × 1
- delete × 1
- dhtmlx × 1
- discriminated union × 1
- distance × 1
- docs × 1
- documentation × 1
- dol × 1
- domain × 1
- du × 1
- duf-101 × 1
- eclipse × 1
- edsl × 1
- em algorithm × 1
- emacs × 1
- emotion × 1
- error × 1
- etw × 1
- euclidean × 1
- event × 1
- example × 1
- ext js × 1
- extension methods × 1
- extra × 1
- facet pattern × 1
- fantomas × 1
- fear × 1
- float × 1
- fp × 1
- frank × 1
- fsdoc × 1
- fsharp.core × 1
- fsharp.powerpack × 1
- fsharpx × 1
- function × 1
- functional style × 1
- gc × 1
- generic × 1
- geometry × 1
- getlastwin32error × 1
- google × 1
- group × 1
- hash × 1
- history × 1
- hosting × 1
- httpcontext × 1
- https × 1
- hubfs × 1
- ie 8 × 1
- if-doc × 1
- inheritance × 1
- installer × 1
- interpreter × 1
- io × 1
- ios × 1
- ipad × 1
- kendo × 1
- learning × 1
- licensing × 1
- macro × 1
- macros × 1
- maps × 1
- markup × 1
- marshal × 1
- math × 1
- metro style × 1
- micro orm × 1
- minimum-requirements × 1
- multidimensional × 1
- multithreading × 1
- mysql × 1
- mysqlclient × 1
- nancy × 1
- nested × 1
- nested loops × 1
- node × 1
- object relation mapper × 1
- object-oriented × 1
- offline × 1
- option × 1
- orm × 1
- osx × 1
- owin × 1
- paper × 1
- parameter × 1
- performance × 1
- persistent data structure × 1
- phonegap × 1
- pola × 1
- powerpack × 1
- prefix tree × 1
- principle of least authority × 1
- programming × 1
- projekt_feladat × 1
- protected × 1
- provider × 1
- ptvs × 1
- quant × 1
- quotations × 1
- range × 1
- raphael × 1
- razor × 1
- rc × 1
- real-time × 1
- reference × 1
- restful × 1
- round table × 1
- runtime × 1
- scriptcs × 1
- scripting × 1
- service × 1
- session-state × 1
- sitelet × 1
- stickynotes × 1
- stress × 1
- strong name × 1
- structures × 1
- tdd × 1
- template × 1
- tracing × 1
- tsunamiide × 1
- type inference × 1
- type providers × 1
- upload × 1
- vb × 1
- vb.net × 1
- vector × 1
- visual f# × 1
- visual studio 11 × 1
- visual studio shell × 1
- visualstudio × 1
- web api × 1
- webapi × 1
- windows 8 × 1
- windows-phone × 1
- winrt × 1
- xml × 1
|
Copyright (c) 2011-2012 IntelliFactory. All rights reserved. Home | Products | Consulting | Trainings | Blogs | Jobs | Contact Us |
Built with WebSharper |
I've been attempting to setup the equivalent of the Haskell State monad with an F# workflow.
However, how do I create the equivalent of "get" and "set" for the state? i.e.,
class MonadState m s | m -> s where get :: m s put :: s -> m () instance MonadState (State s) s where get = State $ \s -> (s,s) put s = State $ \_ -> ((),s)This is what I have so far:
module State = type State<'s,'a> = State of ('s -> 'a * 's) let runState (State s) = s let returnState (v: 'a) : State<'s, 'a> = State (fun s -> v, s) let bindState (x: State<'s,'a>) (f: 'a -> State<'s,'b>) = State (fun s0 -> let v, s1 = runState x s0 runState (f v) s1 ) type StateBuilder<'s>() = member b.Return( x: 'a) : State<'s,'a> = returnState x member b.Bind ( x: State<'s,'a>, rest: 'a -> State<'s,'b>) : State<'s,'b> = bindState x rest member b.Let ( x: 'a, rest: 'a -> State<'s,'b>) : State<'s,'b> = bindState (returnState x ) rest member b.Delay ( rest: unit -> State<'s,'b>) : State<'s,'b> = bindState (returnState ()) rest // setup a dummy example, where the state is an int list. let intListState = new StateBuilder<int list>() let foo n = State (fun s -> n, n :: s) let example = intListState { let! m = foo 1 let! n = foo 2 return (m + n) }Rgds,
Mat