1

This one may be a stupid one but, having a look at (Eliminating my explicit state passing via like, monads and stuff)

type State<'s,'a> = State of ('s -> 'a * 's)

type StateBuilder<'s>() =
  member x.Return v : State<'s,_> = State(fun s -> v,s)
  member x.Bind(State v, f) : State<'s,_> =
    State(fun s ->
      let (a,s) = v s
      let (State v') = f a
      v' s)

let withState<'s> = StateBuilder<'s>()

let getState = State(fun s -> s,s)
let putState v = State(fun _ -> (),v)

let runState (State f) init = f init

what are the advantages of wrapping 's -> 'a * 's in State. Is it just a safety precaution?

Community
  • 1
  • 1
NoIdeaHowToFixThis
  • 4,484
  • 2
  • 34
  • 69
  • this appears to be a duplicate of http://stackoverflow.com/q/2595673/701062 – Gary.S Nov 24 '13 at 22:40
  • @Gary.S That question is asking why the state monad is implemented with functions instead of tuples, not why the state-function is sometimes wrapped in another type. – Jack P. Nov 24 '13 at 22:46

2 Answers2

3

I think it's more a matter of preference or convenience than safety; some people like to wrap the function in a single-case discriminated union type like that, and some don't.

I prefer not to wrap the functions, because it introduces a small amount of additional overhead and can inhibit the compiler from making some optimizations. In my ExtCore library, I've implemented the same thing, using a type alias instead of creating an actual type to wrap the function:

type StateFunc<'State, 'T> = 'State -> 'T * 'State
Jack P.
  • 11,487
  • 1
  • 29
  • 34
2

My guess is the wrapper comes from the Haskell tradition and languages that can generalize over monads. In those laguanges you can have a generic >>= function but you can have only one implementatipon per type and sometimes there are more than one useful implementation.

This is the case of very generic types like 'a * 'b and 'a->'b.

For a function 'a -> 'b you can have a reader, a state or a parser monad defined, the way to tell which implementation pick up is to wrap them, so they have different types.

In F# things are different, most monad libraries don't define a generic >>= implementation since there is no clean way to do this in .NET, so there is no need to wrap the State since you will be explicitely applying a specific implementation of >>= and other monad related functions.

In absence of generic functions or overloads you can still wrap your State monad if you want, but then you'll have to wrap and unwrap code as in Haskell, in this case the decision depends on how much do you want to customize your types and that's a general question, not just with monads.

Community
  • 1
  • 1
Gus
  • 25,839
  • 2
  • 51
  • 76