Thank you all,
In fact, Brandon, I knew about Datatypes a la carte, I just found it overly complicated.
Thanks for you solution, Job. However (and even if it doesn't work without it) I fail to see why you need the functional dependency on Has...
Doesn't it implies here that for one 'a' there can only be one 'b' such as 'Has b a'?
I think you want something like this:{-# Language MultiParamTypeClasses, FlexibleInstances, FunctionalDependencies, UndecidableInstances, FlexibleContexts, OverlappingInstances#-}data Character a = Character { life :: Int,charaInner :: a }deriving (Show)data Gun a = Gun { firepower :: Int,gunInner :: a }deriving (Show)data Armor a = Armor { resistance :: Int,armorInner :: a }deriving (Show)class HasInner f wheregetInner :: f a -> ainstance HasInner Character wheregetInner = charaInnerinstance HasInner Gun wheregetInner = gunInnerinstance HasInner Armor wheregetInner = armorInner
class Has b a | a -> b wherecontent :: a -> binstance (Has b a, HasInner f) => Has b (f a) wherecontent a = content $ getInner ainstance (HasInner f) => Has a (f a) wherecontent a = getInner achara = Character 100 $ Armor 40 $ Gun 12 ()itsGun :: (Has (Gun b) a) => a -> Gun bitsGun = contentYou were missing a mechanism to extract the inner value from your datatypes.- JobOn Wed, Apr 6, 2011 at 2:57 PM, Yves Parès <limestrael@gmail.com> wrote:
Hello Café,
I'm trying to get some modular data types.
The idea that came to me is that I could stack them, for instance :
data Character a = Character { life :: Int,
charaInner :: a }
data Gun a = Gun { firepower :: Int,
gunInner :: a }
data Armor a = Armor { resistance :: Int,
armorInner :: a }
Then a character with a gun and an armor can be build this way:
chara = Character 100 $ Armor 40 $ Gun 12
The idea now is to be able to get some part of the character:
itsGun :: Character ?? -> Gun ??
itsGun = content
Then content would be a class method:
class Has b a where
content :: a -> b
And it would be recursively defined so that:
instance (Has c b, Has b a) => Has c a where
content = (content :: b -> c) . (content :: a -> b)
Then itsGun would be more like:
itsGun :: (Has Gun a) => a -> Gun ??
itsGun = content
But after some juggling with extensions (ScopedTypeVariables, UndecidableInstances, IncoherentInstances...) I can't get it working.
Has someone a simpler way to achieve modular types?
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe