我对Haskell相当新,为了做得更好,我正在努力创建一个简单的Web服务器。我想说明我如何表示可扩展的页面,所以我的想法是让网页成为可渲染数据的列表(比如如何在Java中创建实现某个接口的对象列表),其中Renderable是
class Renderable a where
render :: a -> IO String
不幸的是我了解到列表必须是具体类型,所以我只能列出一种可渲染数据。此外,似乎无法创建受类型类约束的数据,因此我无法创建类似RenderList数据的内容。我的临时解决方案是这样的:
myPage =
[render $ someData
,render $ someMoreData
,render $ someOtherData
...
]
但这感觉很尴尬,使得类型类的使用没有任何好处,并且感觉应该有更好的方法。所以我想知道我可以采用哪些方法来重构我必须更清洁,更符合标准的Haskell实践,并且仍然可以轻松扩展?
感谢。
答案 0 :(得分:9)
您正在尝试实现面向对象的设计风格。例如,在Java中,你有一个List<Renderable>
,你就可以了。这种设计风格在Haskell中不那么自然;你需要为有限的存在主义创建一个包装器类型,如Haskell wiki页面上existential types所示。例如:
class Renderable_ a where
render :: a -> IO String
data Renderable = forall a. Renderable_ a => Renderable a
instance Renderable_ Renderable where
render (Renderable a) = render a
然后,您可以拥有Renderable
的列表,您可以根据需要进行渲染。就像我说的那样,这是一种OO风格,在Haskell中不那么自然。您可以通过重新考虑数据结构来避免这种情况。你说你“想要表达你如何表示可扩展的页面”;考虑其他方式。
无关:我猜render
不需要产生IO String
动作。如果可以的话,尽量让IO
脱离设计的核心。
答案 1 :(得分:3)
在haskell heterogenous collections上查看此页面。 它提供了几种方法的想法。