为什么我们不用 LISP 语法编写 haskell?(我们可以!)

0at*_*man 4 lisp macros haskell defmacro

它......有点工作你们(这绝对编译,改编自https://hackage.haskell.org/package/scotty):

main :: IO ()
main = (do
  (putStrLn "Starting Server....")
  (scotty 3000 (do
    (get "/hello/:name"
        (text ("hello " <> (param "name") <> "!")))

    (get "/users"
      (json allUsers))

    (get "/users/:id"
      (json (filter (matchesId (param "id")) allUsers))))))
Run Code Online (Sandbox Code Playgroud)

(我不知道足够多的 haskell 来转换<>为简单的括号,但聪明的人可以很容易地。)

我们为什么要这样做?我们可以用任何 lisp 宏引擎预处理 Haskell!琐碎!。

想象一下。哈斯克尔和 LISP 在一起。我们可以统治银河系!

在此处输入图片说明

(我知道你的想法,但我实际上已经考虑过了:在这个例子中,Vader 是 Lisp,Luke 是 Haskell,Yoda 是 Alonzo Church)

(编辑“感谢所有回答和评论的人,我现在更聪明了。我认为还没有提到这种技术的最大问题,并由朋友 IRL 指出:如果你写一些 lispy 预处理器,你在你的 IDE 和工具中丢失类型检查和语法突出显示和理解。这听起来对我来说很难。”

“我现在正在关注https://github.com/finkel-lang/finkel项目,这是我想要的 lisp 风格的 Haskell 项目!” )

dan*_*iaz 6

哈斯克尔的语法历史衍生从的ISWIM,这似乎并不比LISP和在彼得J. Landin的1966年的文章中描述晚得多语言下一个700编程语言

第 6 节专门讨论与 LISP 的关系:

ISWIM 可以被视为试图从其对列表的同名承诺、其手到嘴存储分配的声誉、其教学法的硬件依赖风格、其沉重的括号以及与传统的妥协中实现 LISP 。

稍后在同一部分:

ISWIM 的文本外观不像 LISP 的 S 表达式。它更接近 LISP 的 M 表达式(它构成一种非正式语言,用作手动准备 LISP 程序的中间结果)。ISWIM 具有以下附加功能: [...]

所以有明确的意图与 LISP 语法不同,或者至少与 S 表达式不同。

  • @0atman你可以编写相当括号的Haskell(我通常更喜欢使用显式括号而不是`$`运算符),但相似性有点欺骗性,因为括号并不真正表示语言中的列表,并且你不能直接汇编带有列表和原子的代码,您需要 Template Haskell AST。顺便说一句,“&lt;&gt;”的非运算符版本是“mappend”,而“mconcat”组合了整个项目列表。 (3认同)

Car*_*arl 6

在结构上,Haskell 程序由一组模块组成。每个模块由一组声明组成。模块和声明是惰性的——它们的存在本身不会导致任何事情发生。它们只是在编译器用来在生成代码时解析名称的静态命名空间中形成条目。

顺便说一句,你可能会在Main.main这里狡辩。作为入口点,它只是为了被定义而运行。这还算公平。但是,所有其他声明仅在 需要时才用于代码生成Main.main,而不仅仅是因为它存在。

相比之下,Lisps 是更加动态的系统。Lisp 程序由一系列按顺序执行的 s 表达式组成。每一种都会导致具有任意副作用的代码执行,包括修改全局命名空间。

这就是事情变得更多基于意见的地方。我认为 Lisp 的动态结构与其语法的规律性密切相关。语法检查无法区分旨在向全局命名空间添加值的 s 表达式和旨在为它们的副作用运行的表达式。没有句法区分,加个语义区分就显得很别扭了。所以我认为在某种意义上,Lisp 语法过于规则,无法用于 Haskell 中不同类型代码之间具有严格语义分离的语言。相比之下,Haskell 的语法提供了匹配语义差异的句法差异。