根据Structure of a Haskell project的维基百科页面,惯用的haskell项目的src
文件夹如下所示:
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
问题:
我假设Main.lhs
是该计划的主要入口点。这样,我的意思是它包含main
方法,该方法为某些类型IO (a)
返回类型a
的值。是这种情况吗?
.lhs
上Main.lhs
扩展名的含义是什么?为什么不称它为Main.hs
?
我在GitHub上看了一些其他流行的Haskell项目,他们似乎并没有密切关注这个结构。这真的是组织Haskell项目的惯用方法吗?
答案 0 :(得分:9)
是。 The Haskell specification has a paragraph on this topic,你几乎逐字复制语言。
.lhs
表示它是literate Haskell file。在常规的Haskell中,必须将注释标记为特殊注释,并且代码是默认的&#39 ;;在有文化的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
我们有一个Types
模块,可以重新导出Types.*
中的所有内容,以便您import Types
可以获取所有内容,或者,如果您愿意,可以import Types.Internal
或{{ 1}}导入点菜import Types.Gadgets
的子模块。
大图书馆,微小的可执行文件。如果使用Cabal或Stack,则可以设置库目标,然后设置可执行目标,该目标取决于库目标。 Types
和可能的支持模块存在于可执行文件中,它们从库中导入代码。这是测试的理想选择,因为测试是一个单独的目标,也可以依赖于库。如果您希望项目发布其他可执行目标(大型系统的典型代表),您也可以使用它。您的结构可能如下所示:
Main.hs
两者之间有各种各样的选择。 /
lib/
Types/
• Internal.hs
• Gadgets.hs
• Geegaws.hs
Types.hs
src/
• Main.hs
• Utils.hs
• project.cabal
• README.md
和lib/
命名非常惯用。我猜它来自大型C系列项目(特别是GNU项目)倾向于命名的方式。 src/
似乎是一个有趣的名称,每个人都集体选择用于包含代码的目录,该代码将被外部函数接口到Haskell代码中。可以偏离那篇wiki文章,我猜是外卖。
如果您install Stack,您可以创建一个目录并运行cbits/
。堆栈附带默认目录结构(您可以自定义或完全关闭)。可能对比较和对比很有用。