When programming in haskell the :type command is of a great help.
We can quickly understand the purpose of some construct by knowing the arity and signature of a function.
For example:
Prelude Control.Monad.Reader> :type (lift .)
(lift .) :: (Monad m, MonadTrans t) => (a -> m a1) -> a -> t m a1
Is there an equivalent in clojure for knowing the arity of a function (type is not relevant in clojure) ?
For example it was not easy for me at first glance to understand the bellow composition until I realize that (-) and (*) have a variadic arity:
(comp - *)
Personally, I use the REPL. Particularly, (doc), (source), (find-doc) utilities.
For example:
user=> (doc map)
clojure.core/map
([f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls])
Returns a lazy sequence consisting of the result of applying f to the
set of first items of each coll, followed by applying f to the set
of second items in each coll, until any one of the colls is
exhausted.
Any remaining items in other colls are ignored. Function f should accept number-of-colls arguments.
As you can see, it is easy to locate the arity.
I do agree though that Haskell is second to none in this area.
The argument list(s) for a function are stored in the function metadata which you can get using meta:
(:arglists (meta #'*))
Related
Problem Statement
Given n, x, f:
I want output of the form:
[x, f(x), f(f(x)), f(f(f(x))), ..., f^{n-1}(x)]
Existing solution
This can be done via reductions
(reductions
(fn [state _] (f state))
state
(range n))
Question
Is there a primitive that provides a shorter solution?
What you want is clojure.core/iterate, which provides f -> x -> [x, f(x), f^2(x), f^3(x), ...] and clojure.core/take which provides a way to slice the first n elements off of a sequence. take is lazy, as is iterate so there are no guarantees about side-effects.
Is there a way in lisp-family (EDIT: lisp-1) languages to differentiate symbol evaluation with regard to its position as as function or as an argument (i.e. override eval of this symbol in regard to when it is evaluated)?
As an example (I don't need this functionality, this is an example), I wanted to implement some sort of infix operation on a set of objects, which can be called by an object itself
(my-obj some-operator arg1 ...)
which will actually apply function some-operator to my-obj and arguments.
But when this object is used anywhere else in code as an argument, like:
(some-function my-obj &args...)
it will evaluate to a value of my-obj.
Thank you.
In Racket it is possible to do a couple things in this spirit:
You can define a struct and give it a prop:procedure. When an instance of the struct is supplied in an application, the procedure will be called.
You can override the default #%app with your own function, to redefine application generally, and including things that aren't structs. For example you can do things like emulate Clojure's (key map) syntax, so that ('symbol dict) is actually (hash-ref dict 'symbol).
Being a lisp-1 basically means that you do not evaluate the first slot of a combination any differently than any other slots. To get such behavior for code you write anyway, you need to transform it to code that does what you want under the rules of a lisp-1. Thus you will need to implement a macro that performs this transformation.
For example if you want infix operators you need to write some macro infix and then perhaps you could write:
(infix (+ - * /) (1 + 2 * 5 - 3) / 4)
and have it evaluate to 2.
I have been playing around with the idea of a default procedure in a OO CLOS-like Scheme. eg. that writing
(obj 5 10)
Would validate obj and apply it with arguments if obj is a procedure or method, but if it isn't it would be the same as the default dispatcher eg.
(default-dispatcher obj 5 10)
In such Scheme one could make vector accessors:
(define-method default-dispatcher
"Default dispatcher for vectors"
([obj %vector] [index %number]) -> (vector-ref obj index)
([obj %vector] [index %number] value) -> (vector-set! obj index value)
(args ...) -> (error "No such method"))
; example usage
(define vec (vector 4 5 6 7))
[vec 1] ; => 5
[vec 1 10]
[vec 1] ; => 10
In Racket this is possible by changing the languages #%app syntax.
In the TXR Lisp dialect, the problem is approached from the other end. Starting with Lisp-2 dialect as a basis, can we robe ourselves with some of the expressivity advantages of a Lisp-1 dialect, like eliminating the (function ...), #' and funcall noise from programs that make extensive use of higher order functions?
The design is centered around a special operator called dwim, which stands for either "Do What I Mean" or "Dispatch, in a Way that is Intelligent and Meaningful".
Invocations of the dwim operator are sugared over using square brackets, which are called "DWIM Brackets"
The dwim operator isn't just a macro over Lisp-2; it actually changes the name lookup rules. When we have
(dwim a b c (d e f) g)
Or equivalently:
[a b c (d e f) g]
all of the argument forms which are symbolic (a, b, c and g) are resolved using a special rule which conflates together the function and variable namespaces. This is built into the heart of the language. The operator has direct access to the environment to make this possible.
The special treatment does not recurse into (d e f), which is an ordinary Lisp-2 form. You have to put the DWIM Brackets on that if you want the semantics.
Also, the dwim operator is properly handled by macro expansion. For instance, given:
(symacrolet ((localfun whatever))
(flet ((localfun () ...)))
[a b c localfun] ;; refers to the flet as a function object!
(a b c localfun))) ;; refers to the symbol macro!
The macro expander knows about dwim and its semantics, and so it considers the possibility that localfun refers to the function and variable namespace. The closest lexical binding in either namespace is the flet and so the symbol macro expansion is suppressed (shadowed).
The dwim semantics is implicitly used in the partial evaluating op macro and its "cousins" derived from it.
Range Extraction task from Rosetta Code:
(defun range-extract (numbers)
`#{(mapcar [iff [callf > length (ret 2)]
(ret `#[#1 0]-#[#1 -1]`)
(ret `#{#1 ","}`)]
(mapcar (op mapcar car)
(split [window-map 1 :reflect
(op list #2 (- #2 #1))
(sort (uniq numbers))]
(op where [chain second (op < 1)])))) ","}`)
Y Combinator:
;; The Y combinator:
(defun y (f)
[(op #1 #1)
(op f (op [##1 ##1]))])
;; The Y-combinator-based factorial:
(defun fac (f)
(do if (zerop #1)
1
(* #1 [f (- #1 1)])))
;; Test:
(format t "~s\n" [[y fac] 4])
Moreover, various useful things are function callable in TXR Lisp. For instance, every sequence (list, vector or character string) is regarded as a function which maps numeric indices to elements. Thus we can do:
(mapcar "abc" #(2 1 0)) -> #(#\c #\b #\a)
The accepted answer describes a Racket mechanism for treating structures as functions. TXR has this in the form of lambda methods. This is demonstrated in the "OOP-Based" solution to the Accumulator Factory task in Rosetta:
(defstruct (accum count) nil
(count 0))
(defmeth accum lambda (self : (delta 1))
(inc self.count delta))
We can instantiate a (new (accum 9)) which will produce the values 10, 11, 12, ... when invoked as a function. An optional delta argument can be supplied for an increment other than 1:
(let ((acc (new (accum 0))))
(list [acc 5] [acc 5] [acc])) -> (5 10 11)
I saw this code in clojure.core recently.
(defn sort-by
"Returns a sorted sequence of the items in coll, where the sort
order is determined by comparing (keyfn item). If no comparator is
supplied, uses compare. comparator must implement
java.util.Comparator. If coll is a Java array, it will be modified.
To avoid this, sort a copy of the array."
{:added "1.0"
:static true}
([keyfn coll]
(sort-by keyfn compare coll))
([keyfn ^java.util.Comparator comp coll]
(sort (fn [x y] (. comp (compare (keyfn x) (keyfn y)))) coll)))
There is a Comparator type hint on the argument comp. But the two argument version of sort-by passes clojure.core/compare to it. How does this work?
Update:
I would like to know how clojure.core/compare implements java.util.Comparator. compare looks like this:
(defn compare
"Comparator. Returns a negative number, zero, or a positive number
when x is logically 'less than', 'equal to', or 'greater than'
y. Same as Java x.compareTo(y) except it also works for nil, and
compares numbers and collections in a type-independent manner. x
must implement Comparable"
{
:inline (fn [x y] `(. clojure.lang.Util compare ~x ~y))
:added "1.0"}
[x y] (. clojure.lang.Util (compare x y)))
Isnt't this just a normal clojure function?
From jvm/clojure/lang/AFunction.java:
public abstract class AFunction extends AFn implements IObj, Comparator, Fn, Serializable {
/* ...omitted... */
public int compare(Object o1, Object o2){
Object o = invoke(o1, o2);
if(o instanceof Boolean)
{
if(RT.booleanCast(o))
return -1;
return RT.booleanCast(invoke(o2,o1))? 1 : 0;
}
Number n = (Number) o;
return n.intValue();
}
}
When the Clojure compiler is compiling functions, it either implements them as derivatives of RestFn (if variadic) or AFunction (otherwise); however, RestFn extends AFunction, so it all ends up at the same place.
So: All Clojure functions implement Comparator through AFunction, either directly or indirectly.
UPDATE: Below is my answer based on my confusion on what was asked: I thought the question was about the 3-arity overload instead of the 2-arity overload.
I think the confusion comes from the phrase "the two argument version of sort-by passes clojure.core/compare to it". That's not right. Let's see the code:
(. comp (compare (keyfn x) (keyfn y)))
It's using the "dot special form" (see the . as first element of the list). It's being used here as a method call. It will call the method compare on the instance represented by comp with the args (keyfn x) (keyfn y). clojure.core/compare has nothing to do here. From the various forms of dot expressions, this matches the following case:
(. instance-expr (method-symbol args*))
About the type hint: it's just a performance optimization to avoid reflection in that method call.
I've seen two sources that say the following is an identity monad. But I don't think that's true because it fails the Third Monad Law.
(defn result [v] (fn [] v))
(defn bind [mv f] (f (mv))
Fails the Third Monad Law
(bind (bind (result 3) identity) identity)
The inner bind call returns 3, which is not a monadic value, so Java returns the error of trying to call the function (3).
Am I missing something?
The definitions of bind and result are fine, and do constitute a monad. However, identity is not a legal function to pass to bind for your monad. In Haskell, that would not pass the typechecker, because
bind :: (Monad m) => m a -> (a -> m b) -> m b
The second argument here is your f, in this case identity. But identity :: a -> a does not fit with the type required for bind's f.
In order to use something "identity-like" in your monad, you need to lift identity into the monad by composing it with result. For example,
(let [id (comp result identity)] ;; or (liftm identity), if you have liftm
(bind (bind (result 3) id) id))
returns (result 3), ie (fn [] 3).
Edit
I did some more thinking about this, since my assertion that a -> a is an incompatible type with a -> m b is clearly not quite right: if you let a be m b, the types do match. So it's okay to use identity as the bind function in some cases. Specifically, if your original input is (result (result 3)), you can bind identity and get out just (result 3). In fact, (bind identity x) is basically (join x)! This is not exactly news - I've read it multiple times - but I guess it hadn't sunk in, or I'd have answered this question more correctly to begin with.
Anyway, just thought I'd share this, since it's a bit topical and should flesh out my answer a bit.
There has been some outstanding work with Monads in Clojure by Konrad Hinsen, Jim Duey and Leonardo Borges.
My question is - is it possible to do the Free Monad in Clojure?
This is an example in Haskell from an article on Scala:
data Free f r = Free (f (Free f r)) | Pure r
This is the corresponding Scala example
sealed abstract class Free[S[+_], +A](implicit S: Functor[S]) {
final def map[B](f: A => B): Free[S, B] =
flatMap(a => Return(f(a)))
final def flatMap[B](f: A => Free[S, B]): Free[S, B] = this match {
case Gosub(a, g) => Gosub(a, (x: Any) => Gosub(g(x), f))
case a => Gosub(a, f)
}
...
}
It can definitely be done, but a key thing is that the idiomatic Haskell implementation of free monads is based on exploiting the type system to provide a certain kind of modularity and well-formedness guarantees. The idioms used may well not be idiomatic in Clojure, and it might be best to come up with a different sort of implementation.
Just look at the full definition of the Free monad in Haskell:
data Free f r = Free (f (Free f r)) | Pure r
instance Functor f => Monad (Free f) where
-- Construct a "pure value" leaf node
return = Pure
-- Replace every "pure value" leaf node with the tree obtained by
-- applying `f` to its value. (Remember that Haskell is lazy, so this
-- tree is only created as it is consumed, and only those branches that are
-- in fact consumed.)
Pure a >>= f = f a
Free fa >>= f = Free (fmap (>>=f) fa)
This is using the following Haskell features:
Type classes: Functor and Monad
Recursive data types: Free is a recursive type
Higher-kinded polymorphism: note that the type variable f in Free f r is actually used as a type constructor—the definition is abstracting over a container type while constraining the element type.
Then it's also using a type-level fixed point construction, a technique that doesn't exist in Clojure. The simplest version of this is this type:
newtype Fix f = Fix (f (Fix f))
If you've ever read about the Y combinator, you can think of this as an analogue of it, but at the level of types, not of values.
But putting aside all that, let's focus on the essential structure here: a free monad is basically a kind of lazily generated, possibly infinite tree structure. The Functor used in a free monad does two things:
Define what types of nodes exist in the tree, and what data is carried at each node
Allow the generic free monad code to map a function over the children of any node.
(Don't fall into the misconception of looking at the free monadic tree as an "abstract syntax tree"; the nodes of the tree don't represent expressions or anything like that.)
The core generic free monad code then provides two things:
A Pure node type that is guaranteed to exist in every free monad. These nodes just contain a value, and no children.
A bind method that lazily replaces all of the Pure leaves with the result of applying their value to a function.
After you have this, by supplying a suitable functor you can use the generic free monad code to construct lazy trees according to the structure that your functor provides. These trees are just inert values; you consume them by writing interpreter functions that navigate the tree according to some strategy in order to produce the results you need. But actually, you'd want your free monad library to have some suitable generic utility functions to help you write interpreters more easily. For example:
-- | Generic recursive fold over a free monadic tree.
iter :: Functor f => (f a -> a) -> Free f a -> a
iter f (Pure a) = a
iter f (Free fa) = f (fmap (iter f) fa)
-- | If you can map any node to a corresponding action in another monad, you can map
-- the whole free monadic tree to a monadic action as well...
interpret :: (Functor f, Monad m) => (forall x. f x -> m x) -> Free f a -> m a
So the obvious question if one wants to write this in Clojure (or any other Lisp) is: why would one do this instead of just writing an s-expression DSL interpreter?
Well, one thing free monads give you is a kind of normal-form representation of monadic programs. For example, think of the following similar snippets of Clojure and Haskell code:
;;; Clojure; these two expressions always produce the same result and
;;; have the same effects
(do a (do b c))
(do (do a b) c)
-- Haskell counterparts
(a >> b) >> c
a >> (b >> c)
The s-expression syntax in the Clojure forms allows you to write two different expressions that nonetheless are required to always behave the same. In Haskell, on the other hand, the Free monad definition guarantees that the two expressions above evaluate to exactly the same value—no program can distinguish them! So you could write a buggy s-exp interpreter or macro that treated those two Clojure forms differently, but not so for the free monadic trees.
Another set of potential advantages are that free monads provide some standard techniques for implementing language features like backtracking (use some kind of list as your functor, representing alternatives in the order in which they are to be considered) and pausing/resuming the interpretation of a program (free monads are closely related to continuation-passing style).
But for maximum idiomaticity in a Lisp, you probably want to combine both techniques: use s-exprs as a front end that you translate, using some generic library, to a free monad representation according to client-supplied definitions of the special operations of the DSL. Provide also generic functions to simplify the client's task of writing interpreters for their free monadic language.
Yes, following Luis Casillas answer, here is an implementation in clojure of the Free monad in clojure.
(use 'clojure.algo.monads)
;; data Free f r = Free (f (Free f r)) | Pure r
(defn pure [v] {:t :pure :v v})
(defn impure [v] {:t :impure :v v })
(defn free-monad
[fmap]
(letfn [
(fm-result [v] (pure v))
(fm-bind [mv mf]
(if (= :pure (:t mv))
(mf (:v mv)) ;; Pure a >>= f = f a
(impure ;; Free fa >>= f = Free (fmap (>>=f) fa)
((fmap (fn [lmv] (fm-bind lmv mf))) (:v mv)))))
]
{
:m-result fm-result
:m-bind fm-bind
:m-zero ::undefined
:m-plus ::undefined
}
)
)
And an example from Why free monads matter:
Definition of toy language.
;; Toy language
;;
(defn output [c n] [{:t :output :v c}, n])
(defn bell [n] [{:t :bell}, n])
(defn done [] [{:t :done}, nil])
(defn toy-fmap [f]
(fn [[e c]]
(if (= :done (:t e))
[e c]
[e (f c)]
))
)
Definition of the monad for the toy language + helper functions
;;
(def tt-monad
(free-monad toy-fmap))
(defn liftF [toy]
(impure ((toy-fmap (fn [c] (pure c))) toy))
)
(defn m-output [x] (liftF (output x nil)))
(defn m-bell [] (liftF (bell nil)))
(defn m-done [] (liftF (done)))
(defn f-m-done [_] (m-done))
And checking some rules :
;; return "a" >>= output is Free(Output "a", ())
;; {:t :impure, :v [{:t :output, :v \a} {:t :pure, :v nil}]}
(with-monad tt-monad
(m-bind (m-result \a) m-output)
)
;; output "a" >>= return is Free(Output "a", ())
;; {:t :impure, :v [{:t :output, :v \a} {:t :pure, :v nil}]}
(with-monad tt-monad
(m-bind (m-output \a) m-result)
)
;; ((output 'A' >> done) >> output 'C')
(with-monad tt-monad
(m-bind (m-bind (m-output \a) f-m-done) (fn [_] (m-output \c))))
;;(output 'A' >> (done >> output 'C')) is output 'A' Done
(with-monad tt-monad
(m-bind (m-output \a) (fn [x] (m-bind (m-done) (fn [_] (m-output \c))))))
This could be improved quite a lot in terms of readability of the data structure.
Comments and improvements most welcome.
These have been two awesome answers, that directly answer your question and should be deferred to.
I'm still learning myself, and would like to expand the question by mentioning that Free Monads are often accompanied with interpreters, and the following is a simple one that I built for the free monad mentioned by #cotarmanach's.
This could should plug and play with his, to provide a printing interpreter to the data structure built in the following domonad expression:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; INTERPRETER
;;
(def pavlov (domonad tt-monad [a (m-output "hi there pavlov")
b (m-bell)
c (m-output "howdya like me now?")
d (m-bell)
e (m-bell)
f (m-bell)
g (m-done)]
g))
(defn bell-interpreter [program]
(let [{ft :t ; free type: impure or pure?
[{t :t
v :v} next] :v} program]
(if (= :pure ft)
"error, shouldn't have a `pure` type"
(case t
:output (do (prn v) (bell-interpreter next))
:bell (do (prn "rinnnng") (bell-interpreter next))
:done "done!"
:otherwise "uh oh, that's not a type I recognize"))))
For each node, check if it's Free/Impure or Pure.
If it's Impure, then it's one of our "defined" types, so we can interpret it. Create a case for each of our "types", and make sure to call the next member of this recursive data type.