2

假设我有一组记录,如

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 类型系统感到非常困惑,并且知道必须有更好的方法来做到这一点。

4

2 回答 2

15

存在量化有很多方法可以做到这一点,但这通常是矫枉过正的。一种更类似于 Haskell 的方法是简单地预先应用foo并保留[IO ()]结果操作的列表,然后您可以sequence稍后运行它们。

于 2012-10-12T19:20:23.200 回答
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
于 2012-10-12T19:27:14.747 回答