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

Replace (#) with (&) #66

Open
RyanGlScott opened this issue Feb 17, 2015 · 9 comments
Open

Replace (#) with (&) #66

RyanGlScott opened this issue Feb 17, 2015 · 9 comments

Comments

@RyanGlScott
Copy link
Member

Right now, we have a function (#) :: a -> (a -> b) -> b such that a # f = f a. It works, but there's been talk of using the (#) as a natural transformation instead (currently in the wakarusa repo). With this, we could define natural transformations such as:

instance Transformation Canvas IO DeviceContext where
    (#) = send

However, this would not work for things that we currently use the blank-canvas (#) for, such as grd # addColorStop(0, "#8ED6FF") and (defFont [sansSerif]) { fontSize = 30 # pt }. I think the best way to mitigate such a change would be to use the (&) :: a -> (a -> b) -> b function that was introduced in GHC 7.10 in Data.Function (if one is using an older version of GHC, it's easy to redefine it: a & f = f a). There's also a bit of history in that (&) is also used in lens, so it's not a completely arbitrary choice of name.

@andygill, what are your thoughts?

@andygill
Copy link
Member

Idea: make grd a natural Transformation, and then grd # addColorStop(0, "#8ED6FF") can be made to work, with a bit of persuasion.

@RyanGlScott
Copy link
Member Author

How would a CanvasGradient instance for Natural work? I ask since the type signature for addColorStop(Double, Text) -> CanvasGradient -> Canvas ()—is entirely monomorphic, so I don't see how it admits an instance of Natural, which requires two parametrically polymorphic types.

@RyanGlScott
Copy link
Member Author

The closest thing I can think of is

instance Transformation ((->) CanvasGradient) Identity CanvasGradient where
    grd # f = Identity (f grd)

but that would make grd # addColorStop(0, "#8ED6FF") return something of type Identity (Canvas ()), not Canvas ().

@andygill
Copy link
Member

Currently

 addColorStop :: CanvasColor color => (Interval, color) -> CanvasGradient -> Canvas ()

Here's the trick

addColorStop :: CanvasColor color => (Interval, color) -> ColorCommand ()
type CanvasGradient = Natural ColorCommand Canvas

Thus

grd # addColorStop(0, "#8ED6FF")

@RyanGlScott
Copy link
Member Author

I'm a bit confused. What is ColorCommand?

@andygill
Copy link
Member

data ColorCommand where
  AddColorStop' :: CanvasColor color => (Interval, color) -> ColorCommand ()
addColorStop = AddColorStop'

Which means what is grd?

grd = Natural $ \ f -> case f of 
  AddColorStop' (inv,col) -> Command (AddColorStop (off,rep) <<original-grd :: CanvasGradient>>)

So the grd "adds" the original CanvasGradient, when the Natural transformation is applied.

@RyanGlScott
Copy link
Member Author

Ah. So if I'm understanding you correctly, we would (1) create a separate ADT for "member functions" of CanvasGradient, (2) change CanvasGradient from a wrapper around a buffer number to a Natural, (3) change createLinearGradient and createRadialGradient to return a Natural that gives you original_grd and (4) change the type signature of addColorStop to be compatible with this scheme.

This sounds pretty promising, but it would break some existing blank-canvas code in the wild right now (e.g., diagrams-canvas currently expects addColorStop to take grd as an argument).

@andygill
Copy link
Member

How about

grd # do addColorStop(0.0, "red")
         addColorStop(0.5, "green")
         addColorStop(1.0, "blue")

This is possible with some trickery.

@RyanGlScott
Copy link
Member Author

You're right. I suppose we could use a similar trick to what Canvas does (by having Bind and Return constructors), or we could wrap it in a Free monad.

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