【问题标题】:Instance declarations of uncommon typeclasses in extra module额外模块中不常见类型类的实例声明
【发布时间】:2016-03-19 06:32:46
【问题描述】:

将不常见的类型类的实例声明放在额外的模块中是一种好的方式吗?

作为一个例子,我有这个简单的树类型:

module Data.Tree where

data Tree a = Leaf a
            | Node (Tree a) (Tree a)

假设我想使用 QuickCheck 的 Arbitrary 类型类生成 Tree 类型的随机值(并且不仅可以在测试中使用它们)。

什么是最好的?将它们放在定义 Tree 的同一模块中

module Data.Tree where

import QuickCheck.Arbitrary

data Tree a = ...

instance Arbitrary a => Arbitrary (Tree a) where
    ...

或将实例声明外包给另一个模块以避免在Data.Tree 中对QuickCheck.Arbitrary 的依赖

module Data.Tree.Arbitrary where

import Data.Tree
import QuickCheck.Arbitrary

instance Arbitrary a => Arbitrary (Tree a) where
    ...

还是完全不同的东西?

【问题讨论】:

    标签: haskell typeclass


    【解决方案1】:

    避免孤立实例通常是个好主意:它们总是有利于惊喜,而且很难找到。

    所以,是的,将实例放在定义Tree 的模块中。这会使模块有点炸毁,但这不应该是一个真正的问题。在整个包的总构建时间中,如果您有一个较大的模块或两个较小的模块,这并不重要。

    当您可以完全避免包依赖时,这可能会使孤立实例变得有价值,因为安装包显然比从已安装包中导入模块的性能问题要严重得多。

    【讨论】:

    • 避免包依赖不仅仅是一个性能问题,它是关于避免与可能依赖于不同版本库的其他包的冲突。
    • @AlexeyRomanov:当然可以,但是如果发生依赖冲突,孤儿实例模块可能也无济于事。
    • @leftaroundabout 如果该模块没有暴露,它可能会有所帮助——例如如果它仅在测试套件内部使用,这看起来很可能考虑到问题中对 quickcheck 的明确讨论。
    • @leftaroundabout 它也可以提供帮助,因为您不能包含孤立实例模块,而只能自己定义相同的实例。 (当然,这只适用于 1)你有一个应用程序,而不是一个库,并且没有人依赖 your 包; 2)您没有任何依赖项本身使用孤儿实例模块。)
    猜你喜欢
    • 1970-01-01
    • 2017-01-10
    • 2019-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-21
    • 2011-08-15
    • 1970-01-01
    相关资源
    最近更新 更多