Picture
Picture
is an imitation of a function whose input is an implicit parameter (which in Dotty would just be a context function). It has three type parameters. They are, in order:
- The type
Alg
of the algebras that the picture needs to draw. This is an input to thePicture
and hence it is contravariant. - The type of the effect
F
that the picture will create. - The type
A
of the result the picture will produce when it is drawn. This is usuallyUnit
, as we normally draw pictures just for their effect, but it could be something else.
Thus in effect a Picture
is a function with type Alg[F] => F[A]
.
Pictures Are Values
Algebras do not work directly with Picture
. Instead they work with the F[A]
type that is the output of a Picture
. However, all the syntax
that makes the algebras easier to use, and which we have used in our previous examples, create and consume Picture
. The reason for this is that working with raw algebras requires we wrap everything in methods. Methods are not values; we cannot pass a method to a method nor return a method from a method. Functions are values, but in Scala 2 their input parameters cannot also be implicit parameters. Picture
is like a function with an implicit input parameter. It also provides a bit more structure than using functions directly. When we see a Picture
we know exactly what we’re dealing with.
Drawing Pictures
We can draw a picture to the screen using the draw
method. This is syntax
that depends on a having a `Renderer` effect
in scope. There are other methods provided by the Renderer
effect, as explained in its documentation.
Writing and Converting Pictures
In addition to drawing a picture to the screen we can write it to a file or convert it to some other type. The write
method saves a picture to a file. When we call write we must pass two parameters: a normal parameter that is the file name to use and a type parameter that gives the format of the file. In the example below we save a file as a PNG.
import doodle.core._
import doodle.syntax.all._
import doodle.java2d._
import doodle.effect.Writer._
import cats.effect.unsafe.implicits.global
val picture = circle[Algebra, Drawing](100)
picture.write[Png]("circle.png")
The write
method is syntax
that comes from the `Writer` effect
. There are other methods that allow, for example, specifying a Frame
to use when saving the file.
We can convert a Picture
to a Base64 value using the base64
method. As with write
, this method is syntax
for the `Base64` effect
. The parameters are similar to write
: we must specify a format to encode the picture in but we don’t specify a filename. Instead we get back the result of evaluating the Picture
(the A
in F[A]
which is usually ()
) and a Base64
value.
import doodle.core._
import doodle.syntax.all._
import doodle.java2d._
import doodle.effect.Writer._
import cats.effect.unsafe.implicits.global
val picture = circle[Algebra, Drawing](100)
val (result, b64) = picture.base64[Png]()
Converting Other Types to a Picture
The ToPicture
algebra provides a single method that converts some type (fixed for each instance of ToPicture
) to a F[Unit]
. The corresponding syntax
wraps the result in a Picture
, as is standard for syntax, and therefore gives a way to convert the input type to a Picture
.
The available instances vary depending on the backend. For the Java2D backend, Base64
and BufferedImage
values can be converted to Picture
. For SVG only Base64
is currently supported.
Here is quick example of use. First we create a Base64
value from a Picture
.
import doodle.core._
import doodle.syntax.all._
import doodle.java2d._
import doodle.effect.Writer._
import cats.effect.unsafe.implicits.global
// The value we throw away is the result of evaluating the
// `Picture`, which is `Unit`.
val (_, base64) = circle[Algebra, Drawing](100).base64[Png]()
We can convert it right back to a Picture
using the toPicture
method.
val picture = base64.toPicture
Type Class Instances for Picture
There are a few type class instances defined for Picture
.
Picture[Alg,F,?]
has a Monoid
instance if:
- the algebra has
Layout
andShape
; - the effect type
F
has aFunctor
; and - and the result type has a
Monoid
.
In this case the combine is on
, with identity empty
.
Picture[Alg,F,?]
has a Monad
instance if F
does.