主模块应该放在一个惯用的Haskell项目中?

Geo*_*rge 5 haskell

根据Haskell项目结构的维基百科页面src,一个惯用的haskell项目的文件夹如下所示:

src/           -- For keeping the sourcecode
    Main.lhs     -- The main-module
    App/         -- Use hierarchical modules
      ...
      Win32/     -- For system dependent stuff
      Unix/
    cbits/       -- For C code to be linked to the haskell program
Run Code Online (Sandbox Code Playgroud)

问题:

  1. 我假设这Main.lhs是该计划的主要切入点.由此,我的意思是它包含main返回IO (a)某种类型的类型值的方法a.是这样的吗?

  2. .lhs扩展名的含义是什么Main.lhs?为什么不打电话呢Main.hs

  3. 我在GitHub上看了一些其他流行的Haskell项目,他们似乎并没有密切关注这个结构.这真的是组织Haskell项目的惯用方法吗?

hao*_*hao 9

1.

是.Haskell规范有一个关于这个主题的段落,你几乎可以逐字复制语言.

2.

.lhs表明它是一个有文化的Haskell文件.在常规的Haskell中,注释必须标记为特殊,代码是"默认"; 在有文化的Haskell中,恰恰相反:代码必须标记为默认值,注释是"默认值".正如Knuth所说,"主要思想是将程序视为与人类的沟通,而不是作为计算机的一套指令."

3.

没有事实上的方法来组织Haskell项目.我认为有几种粗糙的无定形思想流派:

  • Blob.将所有内容放入一个目录并Main.hs成为入口点.这对于一次性脚本和小项目非常有用.它使进口变得容易.你只import FooFoo.hs从目录中包含.

  • Blob With Folders.随着时间的推移,你会发现这个和那些模块作为子模块一起存在,这些以及那些模块也是如此.您现在可以创建一个src/目录并将所有文件丢弃.此时您可能会开始像这样组织:

    /
     src/
       • Main.hs
       • Types.hs
       Types/
         • Internal.hs
         • Gadgets.hs
         • Geegaws.hs
     • project.cabal
     • README.md
    
    Run Code Online (Sandbox Code Playgroud)

    在这里,我们有一个Types从该模块重新出口的一切Types.*,让你可以import Types得到的一切,或者,如果你愿意的话,import Types.Internal还是import Types.Gadgets要导入的子模块Types点菜.

  • 大图书馆,微小的可执行文件.如果使用Cabal或Stack,则可以设置库目标,然后设置可执行目标,该目标取决于库目标.的Main.hs和可能的支持模块住在可执行文件,他们导入代码库.这是测试的理想选择,因为测试是一个单独的目标,也可以依赖于库.如果您希望项目发布其他可执行目标(大型系统的典型代表),您也可以使用它.您的结构可能如下所示:

    /
     lib/
       Types/
         • Internal.hs
         • Gadgets.hs
         • Geegaws.hs
       Types.hs
     src/
       • Main.hs
       • Utils.hs
     • project.cabal
     • README.md
    
    Run Code Online (Sandbox Code Playgroud)

两者之间有各种各样的选择.然而lib/,src/命名是非常惯用的.我猜它来自大型C系列项目(特别是GNU项目)倾向于命名的方式.cbits/似乎是一个有趣的名称,每个人都集体选择用于包含将在Haskell代码中进行外部函数接口的代码的目录.偏离那篇维基文章是可以的,我猜是外卖.

如果安装Stack,则可以创建目录并运行stack new.堆栈附带默认目录结构(您可以自定义或完全关闭).可能有用的比较和对比.