Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Universally-generalized constraints

Here's a pretty useful class:

class Foo f a where
  foo :: f a

It let's me make default values for lots of types. In fact, I might not even need to know what a is.

instance Foo Maybe a where
  foo = Nothing

Now I have a Maybe a for all a, and I can specialize it later.

specialize :: (forall a. f a) -> f Int
specialize x = x

fooMaybe :: Maybe Int
fooMaybe = specialize foo

Hmmm....that fooMaybe sure seems pretty specific. Let's see if I can use a context to generalize it:

fooAll :: (Foo f a) => f Int
fooAll = specialize foo

Oops! Guess not.

Foo.hs:18:21:
    Could not deduce (Foo * f a1) arising from a use of `foo'
    from the context (Foo * f a)
      bound by the type signature for fooAll :: Foo * f a => f Int
      at Foo.hs:17:11-28

So, my question is, how can I write fooAll, the generalized version of fooMaybe? Or, more generally, how can I universally-generalize a typeclass constraint?

like image 822
James Koppel Avatar asked May 09 '13 09:05

James Koppel


1 Answers

No good way in current Haskell right now. The constraints package provides a type that might do what you need, although, I recently figured out how to break it. Still probably your best bet, because if someone figures out how to do it right it will probably get updated

fooAll :: Forall (Foo f) => f Int
fooAll = specialize foo_f where
  foo_f :: forall a. f a
  foo_f = foo \\ (inst `trans` (Sub Dict) :: () :- Foo f a)
like image 179
Philip JF Avatar answered Oct 12 '22 22:10

Philip JF