
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). Cheers, -- Dan