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

Pieter Laeremans pieter at laeremans.org
Fri Jun 20 18:44:13 EDT 2008


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 <dan.doel at gmail.com> wrote:
> 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 <pieter at laeremans.org>

"The future is here. It's just not evenly distributed yet." W. Gibson


More information about the Haskell-Cafe mailing list