To initially create a monad instance, use Join.Monadic.apply()
together with a source object of the mapping and an instance of
Join[] which describes a field mapping and a way of joining
fields. For instance, a monad for joining a Car and an
Engine into a CarWithEngine with respect to CarId
described by a Join[CarWithEngine, CarId, Car, Engine] can be
generated as the following.
type HasEngine = Join[CarWithEngine, CarId, Car, Engine]
val hasEngine: HasEngine = ???
val car: Car = ???
val m = Join.Monadic(car, hasEngine)
A monad can implicitly be converted to an option value of the
target type of the join by internally invoking methods of
Join[] in the conversion.
val enginedCar: Option[CarWithEngine] = m
Since it is a monad, the value can mapped to another value in a
for comprehension. (Assume that a CarWithEngine has engine
field of type Engine in the next example.)
val engine: Option[Engine] = for {
car <- m
} yield (car.engine)
Note that the car in the above example, i.e., the argument of
a function passed to flatMap() or map() of the monad, is a
CarWithEngine. You don't need to look inside the option value
in this way. If the resulting option value is None, i.e.,
there is no target value to join, then the body of the function
passed to flatMap() or map() never be invoked.
A list of monadic values can also be converted to a list of
the target list type.
val cars: Seq[Car] = ???
val ms = cars.map { car => Join.Monadic(car, hasEngine) }
val enginedCars: Seq[CarWithEngine] = ms
In this case, cars are mapped to enginedCars by methods in
Join[] all at once. You can of course use a for
comprehension for further operations.
val engines: Seq[Engine] = ms.map { m =>for {
car <- m
} yield (car.engine) }
If you aim to achieve an efficient object join by converting a
list value at once via methods in Join --- this is the most
common reason for using the monadc object join ---, DO NOT
trigger the implicit conversion inside the loop.
val engines: Seq[Engine] = ms.map { m =>val e: Option[Engine] =
/* !!! methods in Join[] are called here !!! */for {
car <- m
} yield (car.engine)
e
}.flatten
It is not difficult to notice the misuse in this way since the
object must be recieved as an Option[Engine] not an Engine
to trigger the conversion for each element.
A factory of a monad for joining object field.
To initially create a monad instance, use
Join.Monadic.apply()
together with a source object of the mapping and an instance ofJoin[]
which describes a field mapping and a way of joining fields. For instance, a monad for joining aCar
and anEngine
into aCarWithEngine
with respect toCarId
described by aJoin[CarWithEngine, CarId, Car, Engine]
can be generated as the following.A monad can implicitly be converted to an option value of the target type of the join by internally invoking methods of
Join[]
in the conversion.Since it is a monad, the value can mapped to another value in a
for
comprehension. (Assume that aCarWithEngine
hasengine
field of typeEngine
in the next example.)Note that the
car
in the above example, i.e., the argument of a function passed toflatMap()
ormap()
of the monad, is aCarWithEngine
. You don't need to look inside the option value in this way. If the resulting option value isNone
, i.e., there is no target value to join, then the body of the function passed toflatMap()
ormap()
never be invoked.A list of monadic values can also be converted to a list of the target list type.
In this case,
cars
are mapped toenginedCars
by methods inJoin[]
all at once. You can of course use afor
comprehension for further operations.If you aim to achieve an efficient object join by converting a list value at once via methods in
Join
--- this is the most common reason for using the monadc object join ---, DO NOT trigger the implicit conversion inside the loop.It is not difficult to notice the misuse in this way since the object must be recieved as an
Option[Engine]
not anEngine
to trigger the conversion for each element.