2014-09-06 70 views
1

我想寫出下列數據結構在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) } 

時是否有允許基於一個類型類的異質收集任何的替代品?

+0

我想Google已經給了你這篇文章,但以防萬一:http://www.haskell.org/haskellwiki/Heterogenous_collections – 2014-09-06 18:33:18

回答

2

如果你確實需要Renderable的列表,你可以使用existentials。

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