在Scalaz trait Foldable
中,我们看到method foldMap
,其中包含以下说明
将结构的每个元素映射到[[scalaz.Monoid]],然后合并结果。
def foldMap[A,B](fa: F[A])(f: A => B)(implicit F: Monoid[B]): B
你可以像这样使用它:
scala> List(1, 2, 3) foldMap {identity}
res1: Int = 6
scala> List(true, false, true, true) foldMap {Tags.Disjunction}
res2: scalaz.@@[Boolean,scalaz.Tags.Disjunction] = true
我的问题是: Scalaz Foldable折叠图的Clojure等价物是什么?
答案 0 :(得分:8)
默认情况下,Clojure没有monadic组合。为此,您需要algo.monads或fluokitten等库。
Haskell和Skalaz中的monoid是一个实现三个函数的类:
mempty
返回标识元素mappend
合并了两个相同类型的值mconcat
用于将该类型的集合转换为项目和v.v。 Clojure没有折叠函数可以调用所有这三个函数; reduce
是用于累积集合的高阶函数。
默认情况下,它需要3个参数:reducer函数,累加器和集合。 reducer函数用于一次合并累加器和集合中的一个项目。它不需要接受像mappend
这样的相同类型。第三个是集合,这就是不需要mconcat
的原因。
在Clojure的1.5 clojure.reducers
和clojure.core/reduce
的上下文中, 是一个monoid但是:一个函数在没有参数的情况下调用时返回它的标识元素。
例如:
(+) => 0
(*) => 1
(str) => ""
(vector) => []
(list) => ()
这个'monoid'函数在reduce
的两个参数版本中用作reducer;调用它的'monoidal identity'或mempty
来创建初始累加器。
(reduce + [1 2 3]) => (reduce + (+) [1 2 3]) => (reduce + 0 [1 2 3])
因此,如果你想在这里翻译这些例子,你需要找到或创建一个具有这种'monoid'实现的函数,以便在双arity reduce中使用它。
对于脱节,Clojure有or
:
(defmacro or
"Evaluates exprs one at a time, from left to right. If a form
returns a logical true value, or returns that value and doesn't
evaluate any of the other expressions, otherwise it returns the
value of the last expression. (or) returns nil."
{:added "1.0"}
([] nil)
([x] x)
([x & next]
`(let [or# ~x]
(if or# or# (or ~@next)))))
它确实有'monoid'实现,([] nil)
。但是,or
实现为支持短路的宏,并且只能在要扩展的表达式中使用,而不能作为函数参数使用:
(reduce or [false true false true true])
CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/or, compiling
所以我们需要一个'new'or
,这是一个真正的析取函数。它还应该实现一个返回nil的非arity版本:
(defn newor
([] nil)
([f s] (if f f s)))
所以现在我们有一个带有'monoid'实现的函数,你可以在双arity reduce中使用它:
(reduce newor [true false true true])
=> true
看起来有点复杂,直到你理解为什么Clojure将or
实现为多个arity宏
(or true false true true)
=> true
答案 1 :(得分:2)
我愿意被证明是错的,但我不认为Clojure有蠢事。但是,请查看描述如何创建幺半群的this article。
特别是对于你的两个例子,我会写:
(reduce + [1 2 3]) ; => 6
和
(some identity [true false true true]) ;=> true
请注意,identity
不 Identity monoid。 : - )