在clojure中,我们应该何时使用monad而不是宏,反之亦然?

zca*_*ate 26 macros monads clojure

monad上有太多的教程说..."看!这里是我们可以使用monad的情况"或"这就是monad的用途".我想知道的是,人们用什么步骤得出他们可以对自己说的结论 - "Gee Whiz!看起来我们可以在这里使用monad!"

所以,当有人告诉我......"(等等)与monad无关......",它真的无助于我回答我的问题,它们是:

  • 我如何确定使用monads表达程序中的哪种模式?
  • 当我发现使用它们的潜力时,如何编写我自己的定制monad?

我在这里开始了一个很长的问题关于monads如果有人有兴趣帮忙 - Map和Reduce Monad for Clojure ...... Juxt Monad怎么样?.

回到这个问题:

什么时候应该使用monad而不是宏,反之亦然?

  • 我读过文章和看过演示文稿,说......'Monad用于DSL抽象'......但是大多数clojure DSL库(例如打嗝和korma)都在使用defmacro并且效果很好.

如果我们有宏,为什么我们需要在clojure中使用monad?

mik*_*era 39

我现在已经使用Clojure两年了,而且我唯一一次使用monad作为练习来证明它可以完成.我从来没有需要它们用于"真正的"代码.

Monads在Haskell中更常见,因为:

  • 它们是处理有状态计算的惯用方法.在Clojure中,您通常使用托管引用处理状态,因此在Clojure中几乎不需要monad.
  • 同样对于IO:Clojure允许您直接执行IO而不在您的类型中声明它,因此您不需要IO monad.

我的建议是专注于Clojure中的标准函数式编程.除非你看到你真的需要 monad,否则我不会投入太多时间来试图引入它们.

宏是一个稍微不同的问题:它们用于编译时代码生成和语言语法的扩展(可能包括DSL,尽管DSL不一定需要宏).当满足以下两个条件时,我使用宏:

  1. 我想以一种显着提高我解决特定问题域的能力的方式扩展语言语法.
  2. 无法使用正常的功能/功能组合获得相同的功能.如果可能,正常函数应该是您的首选:它们通常更易于编写和维护.

PS如果你真的对Clojure的monads感兴趣,这里有两个我个人觉得非常好的视频:

  • 在Haskell中,monad的唯一部分是"语言的一部分"(与标准库相对)是方便的符号,以及它们对I/O的使用. (2认同)
  • @mikera,monads不仅用于处理状态计算,实际上状态monad与托管引用结合使用效果很好.Monad是一种通用的设计模式,你可能已经使用它(或发明它)而没有意识到它.例如,您是否知道Clojure中的序列是monad? (2认同)

khi*_*sen 16

Monads和宏没有任何共同之处.它们用于解决不同的问题.在Clojure中,monad库非常广泛地使用宏来实现monad的语法"用户界面".您可以使用monads在功能上实现某些库,而不是为外部接口添加一层宏.

至于"何时会在Clojure中使用monad",我看到两个用例:

1)在多个monad中实现有意义的东西,以便只做一次这个工作并在以后"插入"monad.以下是这种方法的一个很好的例证,虽然不幸(从教学的角度来看)一个相当重要的应用:逻辑编程.

2)实施可以制定为monad的组合技术,以便从现有的monad基础设施中获利.

Clojure有两个内置monad,"let"(身份monad)和"for"(序列monad).只要您希望以后可以将其中一个插入到代码中,就应该使用"domonad".每当你希望你有类似但不完全相同的东西时,你应该考虑编写自己的monad.

遗憾的是,这仍然相当抽象.目前在Clojure中使用monad的发布和抛光代码示例并不多.随着越来越多的Clojurians熟悉monad和更多Monad专家(通常来自Haskell)使用Clojure,这可能会改变.例如,我已经看过(但没有手头)在Clojure中完成的monadic解析.