20

We can use the extension ConstraintKinds to extend the functionality of the base type classes to allow constraints. For example, we can make an unboxed vector a functor:

class Functor f where
    type FunctorConstraint f x :: Constraint
    type FunctorConstraint f x = ()
    fmap :: (FunctorConstraint f a, FunctorConstraint f b) => (a -> b) -> f a -> f b

instance Functor VU.Vector where
    type FunctorConstraint VU.Vector x = VU.Unbox x
    fmap = VU.map

(See these blog posts for more details).

I have noticed myself implementing a rather large portion of the base library type classes in this new style (basically I want to be able to work interchangeably between unboxed vectors and lists), and am wondering if a library for this already exists that I should use, or if I should flesh mine out and add it to hackage.


Edit: Also, are there plans to add this directly to base? It seems like it shouldn't break anything else just by updating the class definitions directly.

Mike Izbicki
  • 6,286
  • 1
  • 23
  • 53
  • 2
    +1 for an interesting question, and for good choice of links. My guess would be 1. probably not (I didn't look very hard), 2. yes please, and 3. don't get your hopes up just yet; this would turn a language extension on by default. – AndrewC Oct 03 '12 at 07:57
  • 1
    If you find yourself rolling your own Prelude etc, and it genuinely doesn't break anything, why not finish the job and post it as a replacement package of prelude & base classes on hackage via github? You (and other enthusiasts) could add new modules one by one, with a CK suffix or something. We'd all get to play with it and it'd get some community testing and if it's all as lovely as you'd hope, there'd be more traction behind adding it to base. – AndrewC Oct 03 '12 at 07:58
  • 3
    Key Questions: 1. Is there a canonical/inescapably-correct way to add constraint kinds to each class? 2. Is it too great a hurdle for new users? If the answer to these is (yes,no), then it would be nice to be able to switch between base and baseCK with one compiler pragma rather than with a whole load of import Data.MaybeCK type stuff. – AndrewC Oct 03 '12 at 07:58
  • (I deleted my own not-an-answer and refactored as comments.) – AndrewC Oct 03 '12 at 08:00
  • @AndrewC Because you can add the default constraints, there is exactly 0 code rewriting required for instance declarations. Also, I think we *might* be able to use pragmas to selectively turn on/off the little bit of code addition that uses CK based on whether the user has enabled the extension or not. – Mike Izbicki Oct 03 '12 at 16:55
  • Ok, so I'll go ahead and clean up what I've done, post it to hackage, and then update this page. Hopefully it will get done today, but definitely tomorrow sometime. – Mike Izbicki Oct 03 '12 at 16:56
  • The hurdle is more about error messages than code changing - I'm perfectly happy about default constraints for instances. Can you take an erroneous piece of code that gives a straightforward error message now, and compile it unchanged with CK enabled, to get an error message about Constraint Kinds? For example, `False:"Hello"` gives you a type mismatch, but `False + 5` gives you `no instance for (Num Bool)`. Here adding type classes has introduced a less clear error message (with unhelpful suggested possible fix). Can CK confuse beginners who don't know it's being used with new error messages? – AndrewC Oct 03 '12 at 17:50
  • Have you seen [ClassyPrelude](http://hackage.haskell.org/package/classy-prelude)? – DJG Dec 21 '13 at 13:52
  • I noticed that the above example is actually pretty much exactly what I ended up with when trying to do the same thing with `TypeFamilies`, is there anything `ConstraintKinds` does that `TypeFamilies` doesn't? Or on the contrary is there anything dangerous in `TypeFamilies` that `ConstraintKinds` avoids. – semicolon May 04 '16 at 23:29
  • @semicolon The solution above uses both `TypeFamilies` and `ConstraintKinds`, so I'm not sure what you're asking. – Mike Izbicki May 06 '16 at 03:28
  • @MikeIzbicki Oh, well it works just fine without `ContraintKinds` on my machine. – semicolon May 06 '16 at 04:41
  • I doubt that's true, and if it is, it's a bug in GHC. The `:: Constraint` phrase above is the constraint kind. – Mike Izbicki May 07 '16 at 00:19
  • @MikeIzbicki you can doubt all you want. It compiles locally just fine. Maybe it's because I did `import GHC.Prime (Constraint)`? But when I removed that it didn't work even with `ConstraintKinds`. – semicolon May 08 '16 at 18:12
  • You need the `import` line, yes, but you should *also* need `ConstraintKinds` turned on. If not, then you've found a bug in ghc and should report it. – Mike Izbicki May 09 '16 at 00:32

1 Answers1

6

Since it sounds like no one else has a library, I've converted what I've done into a separate project called ConstraintKinds and uploaded it to github. It's extremely simple at the moment and probably doesn't cover any one else's use case yet, but feel free to make your own changes or submit requests.

I will probably wait for more feedback on if this is a good direction before uploading the project to hackage.

Mike Izbicki
  • 6,286
  • 1
  • 23
  • 53
  • I was wondering whether some of this source code could be automatically generated (source code rewriting functions!), but your definition for `Monad` seems inconsistent. Why's that? – AndrewC Oct 04 '12 at 06:36
  • I think template Haskell could be used really well here to make the instances automatically, but I don't know much about that. Also, I haven't actually needed any Monad instances. I just tried whipping together something real quick and so it probably has lots of flaws in it. – Mike Izbicki Oct 04 '12 at 15:26
  • Hi Mike. I think it would be a good idea to have this as a package. But maybe there should be a number of packages like Control.RFunctor, Control.RMonad instead of calling it Control.ConstraintKinds (which is potentially misleading as that is the name of the extension that allows the other classes)? – dorchard Oct 24 '12 at 15:13
  • @dorchard There's a discussion about that over on [reddit that you might find interesting](http://www.reddit.com/r/haskell/comments/10w3cx/ideas_for_a_library_that_uses_constraintkinds_to/). The general consensus was that most people thought the package was a badish idea for various purity reasons. I'm still planning to push it to hackage, though, because I'm writing a library that depends on it. So probably in the next few weeks when I publish the library I'll also publish this package at the same time. – Mike Izbicki Oct 25 '12 at 06:20