
Thanks all!
I have to admit, I have an OO mndset :-).
I think I have found a more "functional design" :
import Text.StringTemplate.Classes
import Text.StringTemplate
data (ToSElem a) => Item a b = Item {cargo::a , catalog :: (Catalog a b)}
instance (ToSElem a) => ToSElem (Item a b) where
toSElem = (toSElem . cargo)
type Id = String
type ItemToSelem a b = Item a b -> SElem b
type ItemParser a b = String -> Item a b
type AllItemReader a b = IO [Item a b]
type SingleItemReader a b = Id -> IO (Item a b)
data Catalog a b = Catalog {reader:: (AllItemReader a b),
singleReader ::( SingleItemReader a b)}
data Content = Content {authort :: String, text:: String}
type ContentItem = Item Content String
What I want to express is that there exists differnet kinds of catalogs which,
depending on how they are configured can read from a file system or a database.
And each catalog can contain a specific type of Item.
For each Item I have to be able to produce the toSELem representation
that subsequently can be used by HStringTemplate
I thik that means I could declare
On Sat, Jun 21, 2008 at 12:26 AM, Dan Doel
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
--
Pieter Laeremans