说我有一组记录,如
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类型系统的影响,并且知道必须有更好的方法来做到这一点。
答案 0 :(得分:15)
有一些方法可以通过存在量化来做到这一点,但它通常是矫枉过正的。更多Haskell-y方法是简单地预先应用foo
并保留[IO ()]
生成的操作列表,然后您可以sequence
运行它们。
答案 1 :(得分:2)
使用Existential
的一个例子,但我真的不愿意使用它,并建议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