如何在Haskell中创建异构集合?

时间:2014-09-06 18:25:33

标签: haskell

我想在Haskell中编写以下数据结构:

Renderable a => [a] -- [ClassOne, ClassTwo, ClassThree]

其中Renderable是类型类

class Renderable a ...

并且所有具体类都实现了类型类

instance Renderable ClassOne ...
instance Renderable ClassTwo ...
instance Renderable ClassThree ...

这方面的一个具体例子是为游戏引擎编写World类。

data World a = World {
    -- ...
    wEntities :: [a]
}

然而,这迫使一个同质的列表。我可以写

{-# ExistentialQuantification #-}

data World = forall r. Renderable r => World {
    -- ...
    wEntities :: [r]
}

但我收到了错误

Record updates for insufficiently polymorphic fields

写作时

world { wEntities = fmap fn (wEntities world) }

是否有任何替代方案允许基于类型类的异构收集?

1 个答案:

答案 0 :(得分:2)

如果你真的需要一个Renderable的列表,你可以使用存在。

class Renderable r where
   render :: r -> IO ()  -- dummy example

data R where
   R :: Renderable r => r -> R
-- or, if you prefer non-GADT syntax,
-- data R = forall r. Renderable r => r -> R

foo :: [R] -> IO ()
foo []         = return ()
foo (R r : rs) = render r >> foo rs

但是,请注意,因为可能不需要这种额外的复杂性,有时会导致antipattern