Here is my problem :
Let's say I have various kinds of objects to handle but they share the same form : We have Items that are made of a String (say an id) and of a Content which can be anything. So the broken-down problem can be summarized as follow : I'd like to be able to produce an item from a content associating it an id in a generic manner but I'd like the type-system to constrain the interface such that I know I'll get back the an Item of the passed content.
Here is an example of an attempt using FunctionalDependencies :
{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE FunctionalDependencies #-} main :: IO () main = do putStrLn $ show $ handleContent TitiAssociation $ read "TitiContent" putStrLn $ show $ handleContent TotoAssociation $ read "TotoContent" -- Expected -- "TitiItem" -- "TotoItem" -- definition of the domain data TitiContent = TitiContent String deriving (Read, Show) data TotoContent = TotoContent String deriving (Read, Show) data TitiItem = TitiItem String TitiContent deriving (Read, Show) data TotoItem = TotoItem String TotoContent deriving (Read, Show) -- class (Read a, Show a) => Content a where class (Read a, Show a) => Item a where instance Content TitiContent where instance Content TotoContent where instance Item TitiItem where instance Item TotoItem where -- Association of types class (Content contentType, Item itemType) => ItemContentAssociation association contentType itemType | association -> contentType, association -> itemType, itemType -> association where -- tokens to identify the types which will be handled data TitiAssociation = TitiAssociation data TotoAssociation = TotoAssociation instance ItemContentAssociation TitiAssociation TitiContent TitiItem where instance ItemContentAssociation TotoAssociation TotoContent TotoItem where -- generic function for handling handleContent :: (ItemContentAssociation association contentType itemType) => association -> contentType -> itemType handleContent TitiAssociation TitiContent = TitiItem handleContent TotoAssociation TotoContent = TotoItem but then the compiler complains :
tmp.hs:41:15: error: * Couldn't match expected type `ass' with actual type `TitiAss' `ass' is a rigid type variable bound by the type signature for: handleContent :: forall ass contentType itemType. ItemContentAss ass contentType itemType => ass -> contentType -> itemType at tmp.hs:40:1-92 * In the pattern: TitiAss In an equation for `handleContent': handleContent TitiAss TitiContent = TitiItem * Relevant bindings include handleContent :: ass -> contentType -> itemType (bound at tmp.hs:41:1) I've also tried various flavours of the TypeFamilies extension but the compiler always complains (could provide more example if required but intended to keep the initial post of a reasonable size at first).
I'm quite new in the world of functionanl programming so do not hesitate to bring up new approaches as I'm sure I'm overlooking many aspects of the problem.
Thanks a lot in advance, Cheers !
handleContenta method ofItemContentAssociation.