On Tue, Aug 7, 2012 at 11:03 AM, Daniel Trstenjak
<daniel.trstenjak@gmail.com> wrote:
Hi all,
it should be possible a call a function on all elements of the data
structure, to add and remove elements.
What I currently have:
the type class:
class Foo a where
hasId :: a -> Int -> Maybe a
a few instances:
data A = A deriving Show
instance Foo A where
hasId a 1 = Just a
hasId _ _ = Nothing
data B = B deriving Show
instance Foo B where
hasId a 2 = Just a
hasId _ _ = Nothing
data C = C deriving Show
instance Foo C where
hasId a 3 = Just a
hasId _ _ = Nothing
the data structure holding any instance of Foo, which itself is a
instance of Foo:
data Foos l r = Foos l r
| FooL l
| FooR r
| NoFoos deriving Show
instance (Foo l, Foo r) => Foo (Foos l r) where
hasId (Foos l r) id =
case (hasId l id, hasId r id) of
(Just l, Just r) -> Just $ Foos l r
(Just l, _ ) -> Just $ FooL l
(_ , Just r) -> Just $ FooR r
_ -> Nothing
combinator for Foos:
(+++) :: l -> r -> Foos l r
l +++ r = Foos l r
infixr 5 +++
Now I can write:
*Main> A +++ B +++ C +++ A
Foos A (Foos B (Foos C A))
*Main> (A +++ B +++ C +++ A) `hasId` 1
Just (Foos A (FooR (FooR A)))
Doesn't seem that nice. For every operation I would have to extend the
type class. After some operations the data structure contains many
dummy nodes (FooR, FooL).
Is there some nicer way?
Read "Data types a la carte". You can use the "free" package for most of the plumbing (I think -- it definitely does free monads, which are a tangentially related idea, but it has a module for dealing with these funny functors, if I recall correctly.)