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

发布于 2024-11-19 11:08:09 字数 1212 浏览 3 评论 0原文

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

假设我想为 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 > 类和基本实例的模块以及没有用于重新导出的模块。

The general question is which module structure is more convenient when adding instances for existing objects? Which pros and cons there are?

Let's say I want to add NFData instance for Seq type. I can place it in:

  • Data.Sequence.Extra (as the same thing is done in the vty package)
  • Data.Sequence.Instances.NFData (more precise)
  • Control.DeepSeq.Instances
  • Control.DeepSeq.Instances.Sequence

It's the case when I don't own neither the type class nor the data type. The other common situation is when I own a type type class and want to add instances for data type(s) from some "heavy" package from Hackage, like OpenGL. Let's say the type class I designed is very light and has no direct relation to OpenGL. I don't want my type class depend on "heavy" package, so I want to place OpenGL instances in a separate module (it's my intuitive feeling, if you have other opinion, let's discuss it). So, what this module should be:

  • MyClass.Instances.OpenGL
  • Graphics.Rendering.OpenGL.Extra (together with instances for other classes)
  • Graphics.Rendering.OpenGL.Instances.MyClass

What is more flexible solution? At some point OpenGL can be replaced with other library, or MyClass can be replaced too. Are there any subtle nuances?

Also, which scheme is better if choose MyClass.Instances variant:

  • MyClass.Class module for the class itself and basic instances and MyClass module reexports it (and maybe MyClass.Instances)
  • MyClass module for the class and basic instances, and MyClass.All reexports everything
  • MyClass module for the class and basic instances and no module for reexporting.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

忆梦 2024-11-26 11:08:10

决定将实例放在哪里的通常过程如下所示:

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

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

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

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

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

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

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

    只有作为最后的手段才考虑创建一个孤立实例。

The usual process of deciding where to put an instance goes something like this:

  1. If you're making a new data type and want an instance for an existing class:

    Put the instance in the same module as the data type.

  2. If you're making a new type class and want to make instances for existing types.

    Put the instances in the same module as the type class.

  3. Both the type class and the data type already exist (your case).

    If the instance is sufficiently general, I'd contact the author of either the type class or the data type and try to convince them to add the instance in their package.

    Otherwise, create a newtype wrapper and write an instance for that.

    Only as a last resort consider making an orphan instance.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文