在Haskell中OCaml模块的等价物是什么?

时间:2014-10-07 23:41:58

标签: haskell module ocaml

我看到的大多数Haskell代码都使用了直接结构,例如列表和树。例如,Haskeller通常会写:

fillRect :: Color → Bounds → Image → Image

该模式存在问题:如果稍后程序员决定修改“Image”的定义,或者使用其他数据结构,那么他将不得不使用它重构每一段代码。在OCaml中,您可以简单地使用一个模块来指定Image的接口,然后再决定具体的实现。

什么是OCaskl模块的Haskell替代方案?

1 个答案:

答案 0 :(得分:12)

有几种选择;没有完全匹配ML模块,但每个方面都有。

  • 参数多态性。您可以在fillRect上参数化您的模块和Image函数,而不是在那些参数上对抽象Image类型 -constructor 进行参数化。指定特定的"种类"图像所以这将是一个像

    这样的签名
    fillRect_ppm :: ImageImplemetation i => Colour -> Bounds -> Image i -> Image i
    

    其中ImageImplemetation是指定转换和/或后端函数之类的类型类 使用这样的解决方案,您无法完全替换 Image类型,但您可以使该类型本身具有任意灵活性。可能,您Image所使用的所有具体类型实际上都会共享某些字段,因此最好不要使其比必要更灵活:ImageImplemetation的不同实例只需要实现他们之间的不同。如果实现非常相似,您可能希望仅对颜色空间等一些细节进行参数化。
    当然,您需要使用此解决方案提前计划,但仅适用于通用接口。如果您定义了必要的实例,您仍然可以稍后将任何类型作为参数。

  • 同样(也可以混合使用),你可以为类型提供一个可以保存图像数据的类型

    fillRect_tcl :: Image img => Colour -> Bounds -> img -> img
    

    Image类将直接定义一些原语,如如何绘制线条,fillRect_tcl将在其实现中使用这些原语。很好,因为fillRect_tcl适用于任何此类类型。有点不好的是,Image类需要相当笨拙(它的首选使用类型类用于"数学"有简单明确的法律的东西。)

    • 也许该类甚至可以将矩形作为一种方法:

      class Image img where
        ...
        fillRect_tcm :: Colour -> Bounds -> img -> img
        ...
      

      不太好,您需要为任何img实例完全重新定义该方法。

  • Haskell的模块系统不能做很多事情,但它仍然足以让你免于重构一切。例如,如果Image来自模块Data.Image,那么您可以完成

    import qualified Data.Image as IM
    
    fillRect_qfi :: Colour -> Bounds -> IM.Image -> IM.Image
    

    并使用该模块中定义的所有函数,也可以使用限定符。如果在某些时候您决定切换实施,您只需更改导入即可 当然,对于类型之间的切换定期来说,这并不是很好,但对于一次性更改则非常好。

非常适合您的示例:diagrams同时使用前两个点;例如rect使用TrailLike类来实现其原语,此类包含as" final"图表类型QDiagram,在您用于渲染的后端进行参数化。