What is the Clojure Scalaz folding folding equivalent?

In the Scalaz Foldable we see a method

+6
source share
2 answers

By default, Clojure does not have a monadic composition. For this you need libraries like algo.monads or fluokitten .

The monoid in Haskell and Skalaz is a class that implements three functions:

  • mempty returns an identity element
  • mappend combines two values ​​of the same type
  • mconcat used to convert collections of this type to elements and vv

Clojure does not have a fold function that calls all three of them; reduce is a function of returning to a higher order for accumulation over a collection.

By default, it accepts 3 parameters: gear function, battery and collection. The reducer function is used to combine the battery and one element from the collection at the same time. It should not accept the same types as mappend . The third is always a collection, so mconcat not required.

In the context of Clojure 1,5 clojure.reducers and clojure.core/reduce there is a monoid: a function that returns an identification element when called without parameters.

For instance:

 (+) => 0 (*) => 1 (str) => "" (vector) => [] (list) => () 

This monoid function is used as a reducer in the two-parameter version of reduce ; its "monoidal identity" or mempty is called to create the initial battery.

(reduce + [1 2 3]) => (reduce + (+) [1 2 3]) => (reduce + 0 [1 2 3])

So, if you want to translate the examples here, you need to find or create a function that has such an implementation of the "monoid" to use it in reducing the arc.

For disjunction, Clojure has 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 ))))) 

He has an implementation of the "monoid", ([] nil) . However, or is implemented as a macro to support a short circuit and can only be used in an expression that needs to be expanded, and not as a function parameter:

 (reduce or [false true false true true]) CompilerException java.lang.RuntimeException: Can't take value of a macro: #'clojure.core/or, compiling 

So, we need a β€œnew” or , which is a true function for disjunction. It should also implement a no-arity version returning zero:

 (defn newor ([] nil) ([fs] (if ffs))) 

So, now we have a function with the implementation of the "monoid", and you can use it to reduce the arc:

 (reduce newor [true false true true]) => true 

It seems a bit complicated until you understand why Clojure implemented or as a macro with multiple arity

 (or true false true true) => true 
+8
source

I am ready to be proved wrong, but I do not think that Clojure has monoids as such. However, check out this article , which describes how you will create a monoid.

In particular, for your two examples, I would write:

 (reduce + [1 2 3]) ; => 6 

and

 (some identity [true false true true]) ;=> true 

Please note that identity not an Identity monoid. :-)

+2
source

All Articles