Generics Haskell中的多种类型列表

Generics Haskell中的多种类型列表,generics,haskell,types,functional-programming,polymorphism,Generics,Haskell,Types,Functional Programming,Polymorphism,假设我有一组记录,如 data A = A { a:: String } deriving (Show) data B = B { b:: String } deriving (Show) 然后是某种类型的类 class Foo a where foo :: a -> IO () instance Foo A where foo c = ... 我也想做一些类似的事情 bar = do push (A {a="x"}) push (B {b="y"})

假设我有一组记录,如

data A = A { a:: String } deriving (Show)
data B = B { b:: String } deriving (Show)
然后是某种类型的类

class Foo a where
    foo :: a -> IO ()

instance Foo A where
    foo c = ...
我也想做一些类似的事情

bar = do
    push (A {a="x"})
    push (B {b="y"})
然后把这些东西放在一个列表里,在以后的某个地方运行,这样我就可以

map foo l

我是否应该编写模板haskell来生成包装器类型并派生实例,以便列表可以是包装器类型?有没有更明智的方法?老实说,我觉得haskell类型的系统束缚住了我,我知道必须有更好的方法来做到这一点。

存在量化有很多方法可以做到这一点,但这通常是过分的。一种更为Haskell-y的方法是,只需在前面应用
foo
,并保留一个
[IO()]
结果操作列表,然后您可以
对其进行排序
,然后运行它们。

一个使用
存在主义
的示例,但我真的不想使用它,并建议hammar所说的

{-# LANGUAGE ExistentialQuantification #-}
data A = A String deriving Show
data B = B String deriving Show

class Foo a where
    foo :: a -> IO ()

instance Foo A where
    foo c = putStrLn $ "FOOA " ++ show c

instance Foo B where
    foo c = putStrLn $ "FOOB " ++ show c

data Wrap = forall a . Foo a => Wrap a

instance Foo Wrap where
    foo (Wrap c) = foo c

bar :: [Wrap]
bar = [Wrap $ A "x", Wrap $ B "y"]

main = mapM_ foo bar

另请参见此上的,以及。因此,您可以使用
thingsToDo=[foo A,foo B]
定义
thingsToDo::[IO()]
,甚至使用
stifftodo=foo A>>foo B