根据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)
问题:
我假设这Main.lhs是该计划的主要切入点.由此,我的意思是它包含main返回IO (a)某种类型的类型值的方法a.是这样的吗?
.lhs扩展名的含义是什么Main.lhs?为什么不打电话呢Main.hs?
我在GitHub上看了一些其他流行的Haskell项目,他们似乎并没有密切关注这个结构.这真的是组织Haskell项目的惯用方法吗?
是.Haskell规范有一个关于这个主题的段落,你几乎可以逐字复制语言.
.lhs表明它是一个有文化的Haskell文件.在常规的Haskell中,注释必须标记为特殊,代码是"默认"; 在有文化的Haskell中,恰恰相反:代码必须标记为默认值,注释是"默认值".正如Knuth所说,"主要思想是将程序视为与人类的沟通,而不是作为计算机的一套指令."
没有事实上的方法来组织Haskell项目.我认为有几种粗糙的无定形思想流派:
Blob.将所有内容放入一个目录并Main.hs成为入口点.这对于一次性脚本和小项目非常有用.它使进口变得容易.你只import Foo和Foo.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.堆栈附带默认目录结构(您可以自定义或完全关闭).可能有用的比较和对比.