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

Use the StateVar package? #61

Closed
ekmett opened this issue Oct 22, 2014 · 30 comments
Closed

Use the StateVar package? #61

ekmett opened this issue Oct 22, 2014 · 30 comments

Comments

@ekmett
Copy link
Member

ekmett commented Oct 22, 2014

We're currently actively working on writing better SDL 2 bindings in sdl2.

For various reasons, it can't depend on the OpenGL package directly, but it needs a state variable construction.

Sadly, not every platform with SDL 2 has OpenGL -- thanks Microsoft.

We'd like to depend on the StateVar package, but then we'll get two versions of the notion of a StateVar that conflict.

By far the cleanest option for us moving forward would be if OpenGL switched to using the external StateVar package that you also maintain, then we could incur a dependency on that.

I realize that when this was last proposed there was some pushback from the Haskell Platform, but otherwise what we're going to start seeing is a profusion of almost-compatible APIs, which is the very thing that the Haskell Platform is meant to prevent.

@ocharles
Copy link

I hope that the presentation of another client in a very close area (lets be honest, most people will be using SDL2 with OpenGL) is ample motivation this time around. This is a very real world scenario :)

@svenpanne
Copy link
Member

Can we bring this up again on the libraries mailing list again? The last time (https://mail.haskell.org/pipermail/libraries/2014-October/023976.html) there was no real outcome, and I have another request for this, see haskell-openal/ALUT#1. Note that we need to split off 3 packages: StateVar/ObjectName/Tensor. Although I'm not sure if this would be a good idea (the 3 packages have already been downloaded a few thousand times), I would be open to some bikeshedding discussions regarding the package names if this makes other people more happy.

Splitting this off again is really the right thing, and given the current relatively dormant state of the Haskell Platform, I'm not sure if previous arguments against that really still hold... 😒

@ekmett
Copy link
Member Author

ekmett commented Mar 7, 2015

Honestly the thing that would keep me from using the StateVar machinery out of the box is the lack of lifting of the operations into MonadIO.

This makes everything incredibly verbose and noisy looking whenever you have local state:

lift $ foo $= bar

vs

foo $= bar

A large part of my mission is to sell people on the fact that Haskell offers them better tools to do their jobs, and frankly, I find the existing API very hard to sell.

@ocharles
Copy link

ocharles commented Mar 7, 2015

@ekmett did you find anything compelling in quine?

@ekmett
Copy link
Member Author

ekmett commented Mar 7, 2015

https://github.com/ekmett/quine/blob/cdaa8216e80e7c501f91fd67b33331c27e97ddac/src/Quine/StateVar.hs is the version I'm using now.

Notably, I make pretty good use out of the Contravariant nature of SettableStateVar's, and found it necessary to separate out updates from mere getting/setting, because otherwise you can't deal properly with atomic updates or transactional variables.

However, i switched to an MPTC based approach, because it let me work better with things like profunctors, IORef's, Ptr's, etc.

For the most part this lets everything "just work".

@svenpanne
Copy link
Member

Well, my StateVar module is much more inflexible than the one from quine, caused by my initial design constraint to work within H98, but I don't think that is very important nowadays. So what about making quine's module a separate package, perhaps even under the already existing StateVar package name? It looks like a more powerful drop-in replacement, so people shouldn't have too much trouble with that. (I haven't looked too closely, though.) This way, OpenGL, GLUT, ALUT, quine, etc. can use a common package, which would be great.

A few more points:

  • Is your foreign-var package a precursor of quine's StateVar module?
  • The ObjectName package is more or less fine for OpenGL-like APIs, perhaps one could generalize the signatures from IO to MonadIO? I've got no strong opinion about that generalization, so it would be good to hear other people's opinion, even if it's "I don't care". 😉
  • I'm a bit unhappy about Tensor, perhaps I should have a look at the vector package, but this would be a heavy API change. Nevertheless, this might be the right thing to do.

@ekmett
Copy link
Member Author

ekmett commented Mar 8, 2015

Is your foreign-var package a precursor of quine's StateVar module?

So what about making quine's module a separate package,

foreign-var is actually a successor to quine's StateVar module. I converted quine to it last night. The #haskell-game folks asked me if I'd split it out.

We bikeshedded the names a bit to avoid conflict with StateVar, and to avoid the drama the name caused last time it was proposed. I'm not terribly attached to the shorter names, however, and we could move it back to the StateVar module and just have it take over as a new version of StateVar.

@svenpanne
Copy link
Member

OK, making foreign-var the new StateVar sounds like a good plan. I think I'll have some free cycles tomorrow to see how this works out with my packages/examples. If everything looks OK, I think this will be the right way. Regarding the actual name: Whatever one chooses, there will be some bikeshedding, so creating a "fait accompli" will be the only way to proceed IMHO. The package has been downloaded a few thousand times already, and creating yet another name for it, even if it might be slightly better, will only create confusion and make things worse.

Would this be OK for you?

@ekmett
Copy link
Member Author

ekmett commented Mar 8, 2015

I'm okay with that. I'll rename the package and module on my local github account, and we can see if we like the result.

@ekmett
Copy link
Member Author

ekmett commented Mar 8, 2015

There may be some upgrade weirdness because I inverted the contravariant dependency, making contravariant depend on foreign-var rather than vice versa, so I'll need to work out a plan that doesn't violate the PVP and my own versioning policy.

@ekmett
Copy link
Member Author

ekmett commented Mar 8, 2015

I've created a foreign-var branch on the StateVar repository which provides a StateVar 1.1 with the API improvements of foreign-var fully integrated, but with the names switched back to StateVar names.

Once (and assuming) you are ready to bless that, I'll ship an updated contravariant package (major version bump) with direct StateVar 1.1 support.

@svenpanne
Copy link
Member

I've tested things locally by making OpenGL's internal StateVar module just re-export Data.StateVar, and everything went smoothly. I made a few tiny fixes to your foreign-var branch and merged it to master, but now Travis CI is a bit unhappy for GHC 7.0.4 and 7.2.2:

https://travis-ci.org/haskell-opengl/StateVar/jobs/53631173
https://travis-ci.org/haskell-opengl/StateVar/jobs/53631174

Can we fix that via some CPP magic? Not being able to support those GHC versions would be a pity, and I'm not even sure if Hackage would be happy with the package (at least there's a warning at the end of the logs about that).

@svenpanne
Copy link
Member

OK, I've added a quick fix for older GHCs, see haskell-opengl/StateVar@51e67f5 and haskell-opengl/StateVar@ece2ad6. If you give me the green light, I can release StateVar 1.1...

@ekmett
Copy link
Member Author

ekmett commented Mar 9, 2015

Sure. We can CPP around the DefaultSignatures and then just not use them
internally in the library.

I'll do that when I get a chance today.

-Edward

On Mon, Mar 9, 2015 at 6:58 AM, Sven Panne [email protected] wrote:

I've tested things locally by making OpenGL's internal StateVar module
just re-export Data.StateVar, and everything went smoothly. I made a few
tiny fixes to your foreign-var branch and merged it to master, but now
Travis CI is a bit unhappy for GHC 7.0.4 and 7.2.2:

https://travis-ci.org/haskell-opengl/StateVar/jobs/53631173
https://travis-ci.org/haskell-opengl/StateVar/jobs/53631174

Can we fix that via some CPP magic? Not being able to support those GHC
versions would be a pity, and I'm not even sure if Hackage would be happy
with the package (at least there's a warning at the end of the logs about
that).


Reply to this email directly or view it on GitHub
#61 (comment)
.

@ekmett
Copy link
Member Author

ekmett commented Mar 9, 2015

Oh you already did it.

On Mon, Mar 9, 2015 at 9:48 AM, Edward Kmett [email protected] wrote:

Sure. We can CPP around the DefaultSignatures and then just not use them
internally in the library.

I'll do that when I get a chance today.

-Edward

On Mon, Mar 9, 2015 at 6:58 AM, Sven Panne [email protected]
wrote:

I've tested things locally by making OpenGL's internal StateVar module
just re-export Data.StateVar, and everything went smoothly. I made a few
tiny fixes to your foreign-var branch and merged it to master, but now
Travis CI is a bit unhappy for GHC 7.0.4 and 7.2.2:

https://travis-ci.org/haskell-opengl/StateVar/jobs/53631173
https://travis-ci.org/haskell-opengl/StateVar/jobs/53631174

Can we fix that via some CPP magic? Not being able to support those GHC
versions would be a pity, and I'm not even sure if Hackage would be happy
with the package (at least there's a warning at the end of the logs about
that).


Reply to this email directly or view it on GitHub
#61 (comment)
.

@ekmett
Copy link
Member Author

ekmett commented Mar 9, 2015

Looks good to me. Pull the trigger whenever you are ready and I'll make a
new release of contravariant.

On Mon, Mar 9, 2015 at 9:49 AM, Edward Kmett [email protected] wrote:

Oh you already did it.

On Mon, Mar 9, 2015 at 9:48 AM, Edward Kmett [email protected] wrote:

Sure. We can CPP around the DefaultSignatures and then just not use them
internally in the library.

I'll do that when I get a chance today.

-Edward

On Mon, Mar 9, 2015 at 6:58 AM, Sven Panne [email protected]
wrote:

I've tested things locally by making OpenGL's internal StateVar module
just re-export Data.StateVar, and everything went smoothly. I made a few
tiny fixes to your foreign-var branch and merged it to master, but now
Travis CI is a bit unhappy for GHC 7.0.4 and 7.2.2:

https://travis-ci.org/haskell-opengl/StateVar/jobs/53631173
https://travis-ci.org/haskell-opengl/StateVar/jobs/53631174

Can we fix that via some CPP magic? Not being able to support those GHC
versions would be a pity, and I'm not even sure if Hackage would be happy
with the package (at least there's a warning at the end of the logs about
that).


Reply to this email directly or view it on GitHub
#61 (comment)
.

@svenpanne
Copy link
Member

@ekmett
Copy link
Member Author

ekmett commented Mar 9, 2015

contravariant is now shipped as well.

Any eta for a new OpenGL?

@svenpanne
Copy link
Member

Soon. 😉 Either in a few hours or tomorrow. I'll splitt off ObjectName, too, and I have to update the other packages, too. I'll have to think about using the vector package, too, but that would be for another release.

Another point: Would it make sense to use MondaIO instead of plain IO in all my packages? AFAICT, this should be basically a drop-in replacement, too. For OpenGLRaw it's easy, I just have to change the generator, for the rest it's just a bit of manual work.

@ekmett
Copy link
Member Author

ekmett commented Mar 9, 2015

I would be a huge 👍 on moving everything into MonadIO.

On Mon, Mar 9, 2015 at 2:19 PM, Sven Panne [email protected] wrote:

Soon. [image: 😉] Either in a few hours or tomorrow. I'll splitt off
ObjectName, too, and I have to update the other packages, too. I'll have to
think about using the vector package, too, but that would be for another
release.

Another point: Would it make sense to use MondaIO instead of plain IO in
all my packages? AFAICT, this should be basically a drop-in replacement,
too. For OpenGLRaw it's easy, I just have to change the generator, for the
rest it's just a bit of manual work.


Reply to this email directly or view it on GitHub
#61 (comment)
.

@svenpanne
Copy link
Member

OK, I'll do the move, but that will delay the release a bit of course. Let's see how many free hacking cycles I have...

@bananu7
Copy link

bananu7 commented Mar 10, 2015

So many liftIO to remove. 👍

@svenpanne
Copy link
Member

[ Short version: I need some help/comments regarding bracket and callbacks. ]

FYI: I'm using the separate StateVar and ObjectName packages in all my OpenGL/OpenAL packages now, this was easy. Furthermore, I've switched almost everything to MonadIO instead of plain IO, but I have a conceptual problem now: What shall I do with functions which internally use bracket and friends? (e.g. withName) Here one can't simply use MonadIO because of bracket's type. The haskeline package has a class MonadException to handle stuff like this, but its instances are incomplete compared to those of MonadIO. (And why on earth is this buried in haskeline? IMHO this should live directly beneath MonadIO itself.) I'm not sure if this is the right approach, so any hints/comments would be highly appreciated.

Another thing to consider is callbacks, e.g. in GLUT or in OpenGL's debug API: AFAICT, these have to use plain IO, because I can't see a way to convert them back to MonadIO. Is this correct? It's not really nice and a bit inconsistent, but probably OK.

@ekmett
Copy link
Member Author

ekmett commented Mar 23, 2015

Take a look at the 'exceptions' package. I created it with Mark Lentczner
to provide a fairly standard place for such a class. It has wide adoption
and is in stackage.

http://packdeps.haskellers.com/reverse/exceptions

Given that it is Mark's baby, getting it into the platform may be a bit
easier than any of the alternatives. ;)

-Edward

On Sun, Mar 22, 2015 at 3:00 PM, Sven Panne [email protected]
wrote:

[ Short version: I need some help/comments regarding bracket and
callbacks. }

FYI: I'm using the separate StateVar and ObjectName packages in all my
OpenGL/OpenAL packages now, this was easy. Furthermore, I've switched
almost everything to MonadIO instead of plain IO, but I have a conceptual
problem now: What shall I do with functions which internally use bracket
and friends? (e.g. withName
https://github.com/haskell-opengl/OpenGL/blob/master/src/Graphics/Rendering/OpenGL/GL/Selection.hs#L79)
Here one can't simply use MonadIO because of bracket's type. The haskeline
http://hackage.haskell.org/package/haskeline-0.7.2.1/docs/System-Console-Haskeline-MonadException.html
package has a class MonadException to handle stuff like this, but its
instances are incomplete compared to those of MonadIO. (And why on earth
is this buried in haskeline? IMHO this should live directly beneath
MonadIO itself.) I'm not sure if this is the right approach, so any
hints/comments would be highly appreciated.

Another thing to consider is callbacks, e.g. in GLUT or in OpenGL's debug
API: AFAICT, these have to use plain IO, because I can't see a way to
convert them back to MonadIO. Is this correct? It's not really nice and a
bit inconsistent, but probably OK.


Reply to this email directly or view it on GitHub
#61 (comment)
.

@svenpanne
Copy link
Member

Ah, nice, thank you! That seems to be exactly what I was looking for, and I was quite sure that there is already something for such an obvious gap in the APIs shipped with GHC, I was just unable to find it. IMHO this package deserves a more prominent place, perhaps it should even be folded into base/transformers.

Perhaps I can polish my OpenGL packages into something really nice before Khronos finishes Vulkan... 😁

@ekmett
Copy link
Member Author

ekmett commented Mar 23, 2015

transformers doesn't implement the classes themselves. As it stands now you can get and use these classes even on ancient platforms that ship with transformers 0.2.

Folding it into mtl would actually reduce support in many ways. It also uses extensions that the mtl does not currently use. (Rank-N types for mask/uninterruptibleMask).

base isn't really in the business of making classes like this. It just doesn't have any today.

Consequently, where it lives now is probably the best compromise we're going to get.

@svenpanne
Copy link
Member

OK, I'm making some progress regarding the generalization of IO to MonadIO/MonadCatch, but I'm hitting a problem now: What can I do with IO actions nested in e.g. allocaArray (see e.g. getHitRecords)? The only way to generalize the IO action is giving up allocaArray and friends and do this via mallocArray/free/bracket by hand. 😞 Or did I miss something? @ekmett to the rescue! 😉

@ekmett
Copy link
Member Author

ekmett commented Mar 24, 2015

In general that combinator isn't safe under a monad transformer.

Consider a version of ListT IO a it has MonadIO, but it'll execute the
future multiple times. If you switched to a manual 'free' your continuation
could free the result several times.

You can limit the 'input' monadic action to IO:

getHitRecords :: MonadIO m => GLsizei -> IO a -> m (a, Maybe [HitRecord])
Trying to allow more is unfortunately lying. You don't have a well-defined
scope.

My usual approach would be to refactor until I wasn't trying to use this
abstraction, but the above is the best legal fix for it.

-Edward

On Tue, Mar 24, 2015 at 6:15 AM, Sven Panne [email protected]
wrote:

OK, I'm making some progress regarding the generalization of IO to MonadIO
/MonadCatch, but I'm hitting a problem now: What can I do with IO actions
nested in e.g. allocaArray (see e.g. getHitRecords
https://github.com/haskell-opengl/OpenGL/blob/master/src/Graphics/Rendering/OpenGL/GL/Selection.hs#L37)?
The only way to generalize the IO action is giving up allocaArray and
friends and do this via mallocArray/free/bracket by hand. [image:
😞] Or did I miss something? @ekmett
https://github.com/ekmett to the rescue! [image: 😉]


Reply to this email directly or view it on GitHub
#61 (comment)
.

@ekmett
Copy link
Member Author

ekmett commented Mar 25, 2015

If we want to get this into the platform, we're going to have to move fast. Otherwise, we'll probably have another year of dealing with the status quo.

@ekmett
Copy link
Member Author

ekmett commented Jun 21, 2015

This has been all done since May 3rd. Closing the issue.

@ekmett ekmett closed this as completed Jun 21, 2015
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

4 participants