在新的堆栈项目中,我打算如何在 src/Lib.hs 和 app/Main.hs 之间拆分代码?

How am I meant to split code between src/Lib.hs and app/Main.hs in a new stack project?

我正在关注 stack guide 并且我得到了一个新的项目设置(耶!)。

它生成了以下文件布局:

.
├── app
│   ├── Main.hs
├── .gitignore
├── LICENSE
├── helloworld.cabal
├── Setup.hs
├── src
│   └── Lib.hs
├── stack.yaml
└── test
    └── Spec.hs

根据指南的“Files in helloworld”部分:

The app/Main.hs, src/Lib.hs, and test/Spec.hs files are all Haskell source files that compose the actual functionality of our project (we won't dwell on them here).

我真的希望他们能仔细考虑一下,因为我不知道 app/Main.hssrc/Lib.hs 之间的区别应该是什么。我应该把哪个代码放在哪里?

我应该如何在 app/src/app/Main.hssrc/Lib.hs 之间划分代码?

如果我只是在编写应用程序或只是在编写库,我是否需要两者 files/directories?

这种将模块分成文件夹的方式可以是您想要的任何方式。天真的想法是你把几乎所有的逻辑都放在 Lib 文件夹中。 Main.hs 然后

  • Lib
  • 导入所需部件
  • 读取命令行参数,
  • 运行东西。

您可以将 app 重命名为 executables 并更改 .cabal 文件中的相应行。实际上,你可以想出一个任意的文件层次结构。

在我们公司的项目中,我们使用了另一种也是非常流行的方法。我们的文件层次结构如下所示:

.
|-- bench
|-- src
    |-- exec1
        |-- Main.hs
    |-- exec2
        |-- Main.hs
    |-- SuperCoolLibrary
        |-- LibModule1.hs
        |-- LibModule2.hs
|-- test
|-- Setup.hs

其他stack.yaml.cabal等文件未在此处显示。

实际上,如果您正在编写一个应用程序,您可以只创建一个 Main.hs 文件并将所有逻辑放在 main 函数中。你不会相信,但作为一名 Haskell 讲师,我从我的学生那里看到了这样的代码:( 虽然我不建议你那样写代码。

如果您正在编写一个库,那么您根本不需要 Main.hs 个文件和 main 个函数。你可以看一个简单的例子,比如这个库(它允许你从数据类型自动生成命令行选项):optparse-generic

希望我能帮助您消除困惑。

即使对于应用程序,它通常也是这样设置的主要原因是为了编写测试。假设您创建了一个名为 foo 的默认堆栈项目,测试套件 foo-test 将依赖于 foo 库,foo-exe 也是如此。如果您要将所有功能放入 app/Main.hs,则无法从 foo-test 测试套件测试这些功能。

如果您只是玩玩而不关心是否有测试套件,您可以将堆栈项目基于 simple 模板:

$ stack new foo simple

如果您想设置测试,我喜欢 tasty。您可以像这样修改 .cabal 文件:

test-suite foo-test
  type:                exitcode-stdio-1.0
  hs-source-dirs:      test
  main-is:             Spec.hs
  build-depends:       base
                     , foo
                     , tasty
                     , tasty-hunit
                     , tasty-quickcheck
  ghc-options:         -threaded -rtsopts -with-rtsopts=-N
  default-language:    Haskell2010

再看看at the example.