Is there a way to refer directly to typeclass instances in Haskell?

  • A+

The benefit of this could be to store certain metadata about the type in a canonical location. Sometimes, it isn't convenient to have a value of the type before using some instance methods on it; For instance if I have:

class Foo a where   foo :: String   foo = "Foo" 

This is not actually valid Haskell. Instead it seems I have to have something like:

class Foo a where   foo :: a -> String   foo = const "Foo" 

and now foo will actually have type Foo a => a -> String, but I would actually like to be able to do something like having a foo with type Instance Foo -> String. For this to be useful in some contexts, it might be also necessary to iterate over all (in-scope?) instances, or in other contexts, to be able to specifically materialize an instance for a given type.

I guess the issue is that instances and typeclasses are not first-class entities in Haskell?


The "old school" way of doing it is providing a "dummy" parameter whose purpose is nothing but helping the compiler find the appropriate instance. In this world, your class would look something like:

data Dummy a = Dummy  class Foo a where     foo :: Dummy a -> String  -- usage: boolFoo = foo (Dummy :: Dummy Bool) 

In fact, this trick was so ubiquitous that the Dummy type was semi-standardized as Data.Proxy.

But in modern GHC there is a better way: TypeApplications.

With this extension enabled, you can just straight up specify the type when calling the class method:

class Foo a where     foo :: String  boolFoo = foo @Bool 

(this doesn't only work for class methods; it will work with any generic function, but be careful with the order of type parameters!)

You may also need to enable AllowAmbiguousTypes in order to declare such class. Though I'm not sure I remember this correctly, and I don't have a computer handy to check.


:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: