如何使用实例组织Haskell模块:坚持数据类型与类型类?

mod*_*lar 13 haskell module instance hierarchy typeclass

一般的问题是在为现有对象添加实例时哪个模块结构更方便?有哪些优点和缺点?

假设我想为Seq类型添加NFData实例.我可以把它放在:

  • Data.Sequence.Extra(在vty包中做同样的事情)
  • Data.Sequence.Instances.NFData (更确切)
  • Control.DeepSeq.Instances
  • Control.DeepSeq.Instances.Sequence

当我既没有类型类也没有数据类型时就是这种情况.另一种常见的情况是,我拥有一个类型类型,并希望从Hackage的一些"重"包中添加数据类型的实例,比如OpenGL.假设我设计的类型类很轻,与OpenGL没有直接关系.我不希望我的类型类依赖于"重"包,所以我想将OpenGL实例放在一个单独的模块中(这是我的直觉,如果你有其他意见,我们来讨论它).那么,这个模块应该是什么:

  • MyClass.Instances.OpenGL
  • Graphics.Rendering.OpenGL.Extra (连同其他课程的实例)
  • Graphics.Rendering.OpenGL.Instances.MyClass

什么是更灵活的解决方案?在某些时候,OpenGL可以替换为其他库,或者也可以替换MyClass.有微妙的细微差别吗?

此外,如果选择MyClass.Instances变体,哪个方案更好:

  • MyClass.Class类本身的模块和基本实例和MyClass模块重新导出它(也许MyClass.Instances)
  • MyClass类和基本实例的模块,并重新MyClass.All导出所有内容
  • MyClass 类和基本实例的模块,没有用于重新导出的模块.

ham*_*mar 12

决定放置实例的位置的常用过程如下:

  1. 如果您正在创建新数据类型并且想要现有类的实例:

    将实例放在与数据类型相同的模块中.

  2. 如果您正在创建一个新类型,并希望为现有类型创建实例.

    将实例放在与类型类相同的模块中.

  3. 类型类和数据类型都已存在(您的情况).

    如果实例足够通用,我会联系类型类或数据类型的作者,并试图说服他们在他们的包中添加实例.

    否则,创建一个newtype包装器并为其编写实例.

    只作为最后的手段考虑制作一个孤儿实例.

  • 我很高兴将孤立实例构建到我的可执行文件中,但我尽量避免将其用于库. (2认同)