I've just wrapped my head around monads (at least I'd like to think I have) and more specifically the state monad, which some people that are way smarter then me figured out, so I'm probably way of with this question.
Anyway, the state monad is usually implemented with a M<'a> as something like this (F#):
type State<'a, 'state> = State of ('state -> 'a * 'state)
Now my question: Is there any reason why you couldn't use a tuple here? Other then the possible ambiguity between MonadA<'a, 'b>
and MonadB<'a, 'b>
which would both become the equivalent ('a * 'b)
tuple.
Edit: Added example for clarity
type StateMonad() =
member m.Return a = (fun s -> a, s)
member m.Bind(x, f) = (fun s -> let a, s_ = x s in f a s_)
let state = new StateMonad()
let getState = (fun s -> s, s)
let setState s = (fun _ -> (), s)
let execute m s = m s |> fst
The State monad essentially works with a type 'state -> 'res * 'state
, which represents a computation that takes some initial state and produces result (together with a new value of the state).
If you're asking whether it makes any difference whether we give some special name to this type (e.g. State<'state, 'res>
) then the answer is it doesn't really matter. The only purpose of giving some special name to the type is that it makes the code more readable. For example, let's look at the two possible type signatures of the following example:
let foo n = state {
let! m = getState()
do! setState(m + 1)
return sprintf "Result: %d" (n * m) }
// Using State<'state, 'res> type:
val foo : int -> State<int, string>
// Using the underlying representation:
val foo : int -> int -> int * state
The first type signature more clearly says that we're writing function in some monad. The second example is just a function that takes two int
values. I think the main benefit of the first one is that you can more easily realize that the type can be used from other monadic computation (written using state { ... }
).
However, as I already noted, this isn't a technical requirement. People probably use this style, because many monads come from Haskell, where monads are associated with the type (such as State<'state, 'res>
) and not a computation builder (such as state
), so it sounds like a good idea to define a new type for every monad in Haskell.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With