Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unexpected behaviour with Picture monad and Java2D renderer #143

Open
zainab-ali opened this issue Jan 8, 2024 · 2 comments
Open

Unexpected behaviour with Picture monad and Java2D renderer #143

zainab-ali opened this issue Jan 8, 2024 · 2 comments

Comments

@zainab-ali
Copy link

The behaviour of the picture monad is a bit different to what I would expect. It discards effects when map is used:

Picture.text("mao").drawToIO() // Draws "mao"
Picture.text("mao").map(identity).drawToIO() // Draws nothing

map is implemented in terms of flatMap, which has the same behaviour:

Picture.text("mao").flatMap(_.pure[Picture]).drawToIO() // Draws nothing

On the other hand, functions such as width which construct a new picture still draw:

Picture.text("mao").width.drawToIO() // Draws "mao"

Is this intended?

@noelwelsh
Copy link
Contributor

Hmmm ... I don't think flatMap can be correctly implemented for Picture.

Consider

Picture.circle(10).flatMap(_ => Picture.square(10))

What should this draw? The problem is that there is no natural way to combine the circle and the square. Often it isn't desirable to combine them. Something like

Picture.circle(10).width.flatMap(w => Picture.square(w * 2))

is a typical usage of width and flatMap, where flatMap is only called so the width can be used to create a different element.

So I think the solution is:

  • Picture has a Functor instance but no Monad
  • Picture has a method andThen that is like flatMap but doesn't obey the monad laws (in particular, it doesn't obey the right identity.)

@zainab-ali
Copy link
Author

Apologies for the delay - I think that's a good approach.

We do still need to define the behaviour of map, andThen and width with respect to drawing.

What do you think about:

Picture.circle(10).width.andThen(w => Picture.square(w * 2)) // Draws the square, but not the circle.
Picture.circle(10).width // Currently draws the circle
Picture.circle(10).map(identity) // === Picture.circle(10) so should draw the circle

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants