我在哪里定义任意实例?

时间:2018-11-24 00:17:15

标签: haskell dependencies code-coverage haskell-stack quickcheck

我不知道在哪里为我的数据类型定义Arbitrary实例。如果我将其放在包中,则包不必要地具有QuickCheck作为依赖项。如果我将其放在测试中 ,则其他程序包将无法使用该实例。如果我将其放在单独的test-utils程序包中,则测试必须生活在单独的程序包中,因此它是一个孤立实例,而 also stack test --coverage却没有。工作。

还有什么其他选择?

1 个答案:

答案 0 :(得分:2)

我通常会选择单独的软件包选项-但是我不使用stack test --coverage。感谢您向我介绍它!

(编辑:我可能会这样做,然后仅在运行stack test --coverage --flag thepackage:arbitrary时使用test flag选项,以便其他任何人都不必处理这些标志。)

也许值得在--coverage问题跟踪器上提出stack问题,因为在这种情况下,覆盖范围检查很有用。

您要求其他选择-最好的选择可能是测试标记。

测试标记

可以在您的阴谋文件中定义一个标志(默认为false),如果选择了标志,它将仅使用QuickCheck依赖项来构建模块。

将所需的代码放在目录arbitrary中(例如)。然后将与以下内容等效的内容添加到package.yaml(第一个代码段)或the-library.cabal(第二个代码段)文件的相关部分:

flags:
  arbitrary:
    description: Compile with arbitrary instances
    default: false
    manual: true

library:
  ⁝
  when:
  - condition: flag(arbitrary)
    dependencies:
    - QuickCheck
    source-dirs:
    - arbitrary
flag arbitrary
  description: Compile with arbitrary instances
  manual: True
  default: False

library
  ⁝
  if flag(arbitrary)
    hs-source-dirs:
      arbitrary
    build-depends:
      QuickCheck

然后,要使用实例的软件包应在其stack.yaml(第1个)或cabal.project(第2个)文件中添加以下内容:

flag:
  the-library:
    arbitrary: true
constraints: the-library +arbitrary

但是有一个小问题……除非该库也定义了这样的标志,否则该库目前无法仅依靠其测试套件中的+arbitrary版本。这可能是值得付出的代价。

注意:我尚未测试下游包装。

Ivan Milenovic's blog可用作初始资源。

DerivingVia /通用实例

由于GHC 8.6已发布,DerivingVia可能还有另一种可能性。 Blöndal, Löh & Scott (2018)中有一个针对Arbitrary实例的案例研究。

您将创建新类型包装器,并为这些新类型实现Arbitrary

它并不能完全避免问题。但是,您可以为这些新类型实现Generic,使使用generic-arbitrary派生的实例与您想要的匹配。


可能还有其他选择。特别地,QuickCheck的依赖性实际上并不那么重。还有其他测试库。另外,请注意,已经有一些讨论将类似Arbitrary的类型类分离到独立的库中。

我还建议使用内部库,但这不允许其他程序包使用您的实例。