I'm looking at doing some interop between clojure and scala. As java itself now has lambdas, I was thinking of a generalisation between data and how to apply a function to a collection
- clojure functions extend
clojure.lang.IFnand generalises collection operations onclojure.lang.ISeq - scala functions extend
scala.Functionand generalises collection operations onscala.collection.Traversable - java lambdas extend
java.util.function.Functionand generalises collection operations onjava.util.stream.Stream
Questions:
- Would monads be useful in this case?
- If so, would a
mapoperation be implemented across all collection types and how might this be generalisable?
Example:
(map (scala-fn +)
[1 2 3]
(scala-seq [1 2 3])
(.stream [1 2 3]))
=> (scala-seq [3 6 9])
Continued (added haskell as a tag just in case the hardcore type people might know)
There are operations in both Clojure, Scala and Java that take a collection, applies a function to that collection and returns a new collection.
- All of these languages run on the JVM.
- However, each language defines it's own class to represent a function.
I'm more familiar with clojure, so there are operations like:
(into {} [[:a 1] [:b 2]]) => {:a 1 :b 2}
Which converts a clojure vector into a clojure map. Because the into operation generalises on java.util.List any datastructure that inherits java.util.List can be used.
I wish to work with some scala libraries in clojure and face certain obstacles:
- Scala, like clojure also has immutable data structures, but they are defined very differently from clojure data structures
- Scala functions inherit from
scala.Functionand so need to be wrapped toclojure.lang.IFn Scala datastructures do not inherit from
java.util.Listwhich means that:(into {} (scala-list [:a 1] [:b 2]))will not work.I'm looking to reimplement some basic clojure functions that also incorporate scala datastructures. (map, reduce, mapcat, etc...)
The functionality would look something like:
(into {} (scala-list [:a 1] [:b 2])) => {:a 1 :b 2}
(into (scala-map) [[:a 1] [:b 2]]) => (scala-map :a 1 :b 2)
(concat (scala-list 1 2) [3 4]) => (scala-list 1 2 3 4)
(concat [1 2] (scala-list 3 4)) => (1 2 3 4) ;lazy seq
(map + [1 2] (scala-list 3 4)) => [4 6]
(map (scala-fn +) [1 2] (scala-list 3 4)) => [4 6]
- What I'm looking for is the ability to use both clojure and scala functions in collection operations.
- I can do this without using monads (by checking the collection and function types and doing some coercing before function application)
- What I'm asking here serves as a bit of a curiosity for me, as all the literature I've read on monads seem to presume that any function
f:X->Yis universal. - However, in the case of clojure/scala/lambda interop, a clojure function, a scala function and a java lambda are not universal. I'm curious about how category theory might be used to solve this problem.