mis*_*tor 40 monads functional-programming clojure option maybe
为什么Clojure尽管如此强调功能范式,却不使用Maybe
/ Option
monad来表示可选值?Option
在Scala中使用非常普遍,Scala是我经常使用的函数式编程语言.
ama*_*loy 48
Clojure不是静态类型的,因此不需要严格的this/that/haskell中必需的任何类型声明(并且,我收集,Scala).如果要返回一个字符串,则返回一个字符串; 如果你改为nil,那也没关系.
"Functional"并不完全对应于"严格的编译时键入".它们是正交概念,Clojure选择动态类型.事实上,很长一段时间以来我无法想象如何实现许多高阶函数,map
并且仍然保留静态类型.既然我对Haskell有一点点(很少)的经验,我可以看到它是可能的,而且往往非常优雅.我怀疑,如果你玩Clojure一段时间,你会有相反的经历:你会发现类型声明不一定能给你一种你习惯用的功能语言.
aga*_*man 24
在Clojure中,nil punning提供了Scala和Haskell从Option&Maybe获得的大部分功能.
**Scala** **Clojure**
Some(1) map (2+_) (if-let [a 1] (+ 2 a))
Some(1) match { (if-let [a 1]
case Some(x) => 2+x (+ 2 a)
case None => 4 4)
}
Run Code Online (Sandbox Code Playgroud)
Scala的Option和Haskell的Maybe都是Applicative的实例.这意味着您可以在理解中使用这些类型的值.例如,Scala支持:
for { a <- Some(1)
b <- Some(2)
} yield a + b
Run Code Online (Sandbox Code Playgroud)
Clojure for macro提供了对seq的理解.与monadic comprehensions不同,此实现允许混合实例类型.
虽然Clojure的for不能用于在多个可能的nil值上编写函数,但它的功能实现起来却微不足道.
(defn appun [f & ms]
(when (every? some? ms)
(apply f ms)))
Run Code Online (Sandbox Code Playgroud)
并称之为:
(appun + 1 2 3) #_=> 6
(appun + 1 2 nil) #_=> nil
Run Code Online (Sandbox Code Playgroud)
Ton*_* K. 17
重要的是要记住,Monad概念与类型无关!类型系统可以帮助您实施规则(但即使是Haskell也无法强制执行所有规则,因为其中一些规则(Monad Laws)无法通过类型系统完全表达.
Monads是关于组合的,这是我们每天在每种编程语言中都做的非常重要的事情.在所有情况下,Monad跟踪一些关于正在发生的事情的"额外背景"......把它想象成一个保持当前价值的盒子.函数可以应用于此值,额外的上下文可以演变为正交关注点.
Maybe类型是关于将长的计算序列链接在一起而不必对失败说什么(这是"额外的上下文").这是一种将"错误处理"从计算中移出并进入Monad的模式.你可以在一个Maybe上串起一系列的计算,一旦失败,其余的都被忽略,最后的结果是"什么都没有".如果它们都成功,那么你的最终结果是monad持有结果值.
这允许您编写更少纠缠的代码.
正如@deterb指出的那样,Clojure支持Monads.
Vag*_*rdi 13
也许/选项是一种类型.它与函数式编程无关.是的,除了功能之外,一些语言(Scala,haskell,ocaml)也提供了一个非常强大的类型系统.人们甚至会说haskell是一个带有TYPES的编程.
其他(clojure,lisp)在类型方面提供的不多,即使它们是功能完备的语言.他们的重点是不同的,并且可能/选项类型不适合.它只是不会给你很多动态语言.例如,对序列(列表,向量,映射)进行操作的许多clojure函数将完全接受null(nil)并将其视为空结构.
(数nil)会给你0.就像(count [])
Clojure不能被称为"带类型的编程",因此Maybe类型在其中没有多大意义.
使用@amalloy 并评论说 Clojure 作为一种语言,不需要可选的返回值。
我在 Scala 方面做得不多,但 Clojure 不需要知道关于返回类型的严格细节就可以处理一个值。这几乎就像嵌入了一个 Maybe monad 并成为正常 Clojure 评估的一部分,因为许多操作,如果在 上执行nil
,则返回nil
。
我快速浏览了 Clojure-Contrib 库,他们有一个monad 包,您可能想查看一下。另一个让我真正了解如何在 Clojure 中使用 Monads 的项目是Cosmin 关于 Clojure 中的 Monads 的教程。正是这一点帮助我了解如何将 Scala 中更明确说明的功能作为动态 Clojure 语言的一部分进行处理。