Data structure containing elements which are instances of the same type class

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? Greetings, Daniel

On Tue, Aug 7, 2012 at 2:03 PM, Daniel Trstenjak
Data structure containing elements which are instances of the same type class
Are you looking for existential quantification [1]? data SomeFoo = forall a. Foo a => a [1]: http://www.haskell.org/ghc/docs/latest/html/users_guide/data-type-extensions...

Hi Joey, On Tue, Aug 07, 2012 at 02:13:09PM -0400, Joey Adams wrote:
Are you looking for existential quantification [1]?
data SomeFoo = forall a. Foo a => a
[1]: http://www.haskell.org/ghc/docs/latest/html/users_guide/data-type-extensions...
Thanks! Yes, that looks really nice. :) data A = A deriving Show data B = B deriving Show data C = C deriving Show data Foo = forall a. Show a => MkFoo a (Int -> Bool) instance Show Foo where show (MkFoo a f) = show a hasId foos id = filter (\(MkFoo a f) -> f id) foos *Main> let foos = [MkFoo A (==1), MkFoo B (==2), MkFoo C (==3)] *Main> hasId foos 1 [A] Greetings, Daniel

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.)
participants (3)
-
Alexander Solla
-
Daniel Trstenjak
-
Joey Adams