[Haskell-cafe] open and closed

Gábor Lehel illissius at gmail.com
Wed Sep 1 14:29:08 EDT 2010

This is probably widely known already but I just realized you can
sort-of have closed classes as it is:

> module SomeModule( SomeClass, someMethod ) where

> class SomeClassInternal a where
>    someMethodInternal :: a -> Integer

> instance SomeClassInternal Integer where
>    someMethodInternal = id

> instance SomeClassInternal [a] where
>    someMethodInternal = fromIntegral . length

> instance SomeClassInternal Bool where
>    someMethodInternal False = 0
>    someMethodInternal True = 42

> class SomeClassInternal a => SomeClass a
> instance SomeClass Integer
> instance SomeClass [a]
> instance SomeClass Bool

> someMethod :: SomeClass a => a -> Integer
> someMethod = someMethodInternal

Basically, not exporting a class is a very obvious way to prevent
people from declaring new instances. The problem is that they also
can't refer to it in any way, and if it shows up in the public API in
a significant way (besides it being just weird) they have to try and
manage their business without using type signatures. The solution is
pretty simple: declare a private class with private methods, and a
corresponding public class which implies the private one, with
instances for all the same types, and have everything in the public
API use the public class instead. That way people still can't declare
new instances for the private class (it's not visible), nor for the
public one (because they can't satisfy the superclass constraint), but
otherwise they're free to use it in type signatures and do whatever
they want.

I don't think the compiler would use this to reason about the code in
new ways (i.e. the typechecker would still treat it as open), but it's
at least something.

(You could also use UndecidableInstances and `instance
SomeClassInternal a => SomeClass a` for less repetition and easier
maintainability; the advantage of not doing so is that you don't need
UndecidableInstances, and the resulting Haddocks are friendlier,
especially if/when Haddock gets updated to hide instances of
non-exported classes.)

More information about the Haskell-Cafe mailing list