[Haskell-cafe] Stacking data types

Yves Parès limestrael at gmail.com
Thu Apr 7 00:13:07 CEST 2011


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 at 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 where
>   getInner :: f a -> a
>
> instance HasInner Character where
>   getInner = charaInner
>
> instance HasInner Gun where
>   getInner = gunInner
>
> instance HasInner Armor where
>   getInner = armorInner
>
>
> class Has b a | a -> b where
>     content :: a -> b
>
> instance (Has b a, HasInner f) => Has b (f a) where
>     content a = content $ getInner a
>
> instance (HasInner f) => Has a (f a) where
>     content a = getInner a
>
> chara = Character 100 $ Armor 40 $ Gun 12 ()
>
> itsGun :: (Has (Gun b) a) => a -> Gun b
> itsGun = content
>
> You were missing a mechanism to extract the inner value from your
> datatypes.
>
> - Job
>
>
> On Wed, Apr 6, 2011 at 2:57 PM, Yves Parès <limestrael at 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 at haskell.org
>> http://www.haskell.org/mailman/listinfo/haskell-cafe
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20110407/b81d1482/attachment.htm>


More information about the Haskell-Cafe mailing list