Monads are Types, that implement two functions with a fixed signature: unit and bind.
In Haskell notation:
unit :: a -> m a
bind :: m a -> (a -> m b) -> m b
unit
wraps an object from type a
into an m
of type a
. The type of a
must be arbitrary. Implementation of bind
can be anything (but it must satisfy the monadic laws).
Let's try to convert your example into Haskell syntax:
People is just a tuple:
type People = (String, String)
The type of Friends is a tripel of two booleans and a String.
If we use these types, than your Friends.unit method is something like this:
unit_friends :: People -> Friends
unit_friends _ = (false, false)
That means, unit_friends
is discarding is parameter and just returning a new instance of Friends
. This is the wrong type signature for unit
. Instead, unit should have this type signature:
unit_friends :: a -> Friends a
In Java, this should look something similar to:
public static Friends<T> unit(T from) {
// return something of type Friends<T>
}
Your bind
function takes a function of type ToFromFunction
and an object of type People
and returns something of type Friends
:
bind_friends :: ToFromFunction -> People -> Friends
Let's replace ToFromFunction
with
type ToFromFunction = People -> Friends -> Friends
because that's the type signature of act
.
bind_friends :: (People -> Friends -> Friends) -> People -> Friends
Let's flip the arguments of bind_friends, because the lambda function should be the second parameter:
bind_friends :: People -> (People -> Friends -> Friends) -> Friends
But it shoud have this type signature:
bind_friends :: Friends a -> (a -> Friends b) -> Friends b
Your types of unit and bind don't match that of a real monad, but it is kind of close.
Let's forget for a moment, that we need an arbitrary type a. The first parameter of bind_friends
must be of type Friends
, not of type People
, because bind
should lift ToFromFunction
to the Friends
monad.