Yep you probably don't need the fundep, you just might need to provide more signatures. It does imply one 'b' for an 'a' which probably isn't what you want.
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'?2011/4/6 Job Vranish <job.vranish@gmail.com>
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