[Haskell-cafe] What's wrong with the classes/insances?

Dan Doel dan.doel at gmail.com
Fri Jun 20 18:26:32 EDT 2008

On Friday 20 June 2008, Pieter Laeremans wrote:
> type Id = String
> class Catalog a where
>     listItems :: a -> IO [String]
>     getItem :: a -> Id -> IO (Maybe String)
> class Item a where
>     getCatalog :: Catalog catalog => a -> catalog
> data Catalog c => Content c = Content {auteur :: String, inhoud::
> String, catalog::c}
> instance Catalog c => Item (Content c) where
>    getCatalog (Content  _ _ c) = c
> I get this as error from ghci:
>     Couldn't match expected type `catalog' against inferred type `c'
>       `catalog' is a rigid type variable bound by
>                 the type signature for `getCatalog'
>                   at
> ../Sites/liberaleswebsite/www.liberales.be/cgi-bin/Test.hs:16:26
>       `c' is a rigid type variable bound by
>           the instance declaration
>             at
> ../Sites/liberaleswebsite/www.liberales.be/cgi-bin/Test.hs:20:17 In the
> expression: c
>     In the definition of `getCatalog': getCatalog (Content _ _ c) = c
>     In the definition for method `getCatalog'
> Failed, modules loaded: none.

The problem is in the type of getCatalog:

  (Item a, Catalog catalog) => a -> catalog

That type says that given the a, you can produce a value of any type 'catalog' 
so long as that type is an instance of Catalog.

What you probably meant it to say is that you can produce *some particular* 
type that belongs to catalog. There are a couple ways you could express this. 
For instance, using functional dependencies:

    class Catalog cat => HasCatalog a cat | a -> cat where
      getCatalog :: a -> cat

or the new type families:

    class (Catalog (Cat a)) => Item a where
      type Cat a :: *
      getCatalog :: a -> Cat a

Or you could wrap catalogues in an existential type:

    data SomeCatalog = forall c. Catalog c => Cat c

    class Item a where
      getCatalog :: a -> SomeCatalog

However, as just a word of warning, I'd say that when you run into something 
like this, it's probably an indication that you're structuring your program 
from an object oriented mindset, and that may not be the best fit for 
programming in Haskell (of course, it's possible an existential type or some 
such is the appropriate way to do things).

-- Dan

More information about the Haskell-Cafe mailing list