Discussion:
Monads in Clojure
(too old to reply)
Konrad Hinsen
2008-11-21 11:14:26 UTC
Permalink
As a first non-trivial exercice, I wrote an implementation of monads
in Clojure. I just uploaded it to the Group:

http://clojure.googlegroups.com/web/monads.clj

The file contains the macro definitions, the definitions of three
popular monads (maybe, list, state), and some illustrations of their
use. Comments are welcome!

One thing I was wondering about: if I want to turn this into a
library module, where could I place it in Java's namespace hierarchy?
I don't have my own domain (and don't need one), and even though I
could have it hosted somewhere (such as SourceForge), it doesn't look
like a good idea to have the package name depend on a hosting site
that might not be forever. How do others approach this problem?

Konrad.
walterc
2008-11-21 14:01:31 UTC
Permalink
how about clojure-contrib?
As a first non-trivial exercice, I wrote an implementation of monads  
       http://clojure.googlegroups.com/web/monads.clj
The file contains the macro definitions, the definitions of three  
popular monads (maybe, list, state), and some illustrations of their  
use. Comments are welcome!
One thing I was wondering about: if I want to turn this into a  
library module, where could I place it in Java's namespace hierarchy?  
I don't have my own domain (and don't need one), and even though I  
could have it hosted somewhere (such as SourceForge), it doesn't look  
like a good idea to have the package name depend on a hosting site  
that might not be forever. How do others approach this problem?
Konrad.
Konrad Hinsen
2008-11-21 15:06:12 UTC
Permalink
Post by walterc
how about clojure-contrib?
Actually, I have no idea of how clojure-contrib works. Is this a
repository for all kinds of Clojure add-ons? Or stuff selected by
Rich for a specific reason?

Konrad.
Stuart Sierra
2008-11-21 15:27:12 UTC
Permalink
Post by Konrad Hinsen
Actually, I have no idea of how clojure-contrib works. Is this a
repository for all kinds of Clojure add-ons? Or stuff selected by
Rich for a specific reason?
Rich gives out commit permission on clojure-contrib to people who are
interested, but he doesn't dictate what goes in. You have to sign the
Clojure Contributor agreement, which basically says that if the
Clojure license changes at some point, you allow your contribution to
be released under the same license (still open-source, of course).
-Stuart Sierra
jan
2008-11-22 00:45:00 UTC
Permalink
Post by Stuart Sierra
Rich gives out commit permission on clojure-contrib to people who are
interested, but he doesn't dictate what goes in. You have to sign the
Clojure Contributor agreement, which basically says that if the
Clojure license changes at some point, you allow your contribution to
be released under the same license (still open-source, of course).
This paper

http://www.rosenlaw.com/OSL3.0-explained.pdf

suggests an alternative to contributor agreements that might be worth
considering.

Here is the relevant section:

This is also a function that can be performed by the Academic Free
License. AFL 3.0 is identical to OSL 3.0 except that licensees are
now free "to distribute or communicate copies of the Original Work
and Derivative Works to the public, under any license of your choice
that does not contradict the terms and conditions, including
Licensor's reserved rights and remedies, in this Academic Free
License." That makes AFL 3.0 a suitable contributor license to other
open source projects, especially (but not only) those projects
distributing software under OSL 3.0. The project is then free to
revise its outgoing license in accordance with its bylaws and charter
as the times dictate.

Instead of a contributor agreement, then, I often recommend that
contributors offer their contribution to a project by placing the
following notice adjacent to their copyright notice:

Licensed to Project XYZ under the Academic Free License (AFL 3.0).
Chouser
2008-11-21 16:10:54 UTC
Permalink
On Fri, Nov 21, 2008 at 6:14 AM, Konrad Hinsen
Post by Konrad Hinsen
As a first non-trivial exercice, I wrote an implementation of monads
http://clojure.googlegroups.com/web/monads.clj
This is pretty code. Did you just implement symbol-macro-let? Very nice.

I noticed that you have a private function (monad-expr) used by a
macro, and was about to comment that that doesn't work -- but your
function is used by the macro, not the *expansion* of the macro, so it
should work just fine. I'll have to keep that in mind.

(zero? n) is an idiom for (= 0 n)

Alas even your beautiful, succinct implementation and careful code
comments are apparently insufficient for me to understand monads.

I'll keep trying. :-)

--Chouser
Konrad Hinsen
2008-11-21 16:40:02 UTC
Permalink
Post by Chouser
On Fri, Nov 21, 2008 at 6:14 AM, Konrad Hinsen
Post by Konrad Hinsen
As a first non-trivial exercice, I wrote an implementation of monads
http://clojure.googlegroups.com/web/monads.clj
This is pretty code. Did you just implement symbol-macro-let?
Very nice.
Thanks! I don't know what symbol-macrolet is/does, so I can't
comment on that. It's probably some Common Lisp thing, right?
Post by Chouser
I noticed that you have a private function (monad-expr) used by a
macro, and was about to comment that that doesn't work -- but your
function is used by the macro, not the *expansion* of the macro, so it
should work just fine. I'll have to keep that in mind.
Yes, it is used only at expansion time.
Post by Chouser
(zero? n) is an idiom for (= 0 n)
Good to know!

Konrad.
Chouser
2008-11-21 17:36:53 UTC
Permalink
On Fri, Nov 21, 2008 at 11:40 AM, Konrad Hinsen
Post by Konrad Hinsen
Thanks! I don't know what symbol-macrolet is/does, so I can't
comment on that. It's probably some Common Lisp thing, right?
Probably, though when googling it just now, I seem to have found some
third-party implementations, so who knows.

My impression, though, is that it provides the ability to define a
local macro where the macro doesn't need to be called from the head of
a list, but is just a symbol that can be dropped in anywhere. Perhaps
someone who actually knows something about a lisp other than Clojure
can comment.

--Chouser
Konrad Hinsen
2008-11-25 14:06:53 UTC
Permalink
Post by Chouser
This is pretty code. Did you just implement symbol-macro-let?
Very nice.
I just saw a reference to symbol-macrolet with a description. My
function replace-syms is indeed very similar, the difference being
that it takes a map for defining the substitutions to be done,
instead of a let-like sequence. The difference is not just in syntax
though, as expressions in symbol-macrolet can refer to earlier
"bindings" (they aren't really bindings) whereas my replace-syms
doesn't check for substitutions to be made inside other
substitutions. But it would be fairly easy to implement symbol-
macrolet on top of my replace-syms. Would that be something of
interest to the Clojure community?

Konrad.
Stephen C. Gilardi
2008-11-25 14:14:58 UTC
Permalink
Post by Konrad Hinsen
But it would be fairly easy to implement symbol-
macrolet on top of my replace-syms. Would that be something of
interest to the Clojure community?
I have no experience with it myself, but I've seen it discussed as
something that would be a welcome addition to Clojure.

It's on Rich's to-do list as the second item listed under "Long-term":

http://richhickey.backpackit.com/pub/1597914

--Steve


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups "Clojure" group.
To post to this group, send email to ***@googlegroups.com
To unsubscribe from this group, send email to clojure+***@googlegroups.com
For more options, visit this group at http://groups.google.com/group/clojure?hl=en
-~----------~----~----~----~------~----~------~--~---
Konrad Hinsen
2008-12-02 10:24:28 UTC
Permalink
Post by Konrad Hinsen
I just saw a reference to symbol-macrolet with a description. My
function replace-syms is indeed very similar, the difference being
that it takes a map for defining the substitutions to be done,
instead of a let-like sequence. The difference is not just in syntax
though, as expressions in symbol-macrolet can refer to earlier
"bindings" (they aren't really bindings) whereas my replace-syms
doesn't check for substitutions to be made inside other
substitutions. But it would be fairly easy to implement symbol-
macrolet on top of my replace-syms.
After having read more on macrolet and symbol-macrolet, I no longer
agree with my earlier self ;-)

symbol-macrolet does not do a simple substitution, it creates a
binding-like environment from which replacements are done repeatedly
as other macros are expanded. I haven't yet found a complete
description of how macros and symbol-macrolet work together. A macro
can expand into code that contains a symbol defined in symbol-
macrolet, and the expansion of such a symbol can produce code
containing macros. I'd expect everything to be expanded repeatedly
until the form no longer changes, but I haven't see this being stated
explicitly anywhere.

In any case, implementing macrolet and symbol-macrolet is probably
not a trivial project. I see basically two approaches:
1) Full repeated expansion of the form, which is then handed to the
compiler.
2) Implementation as an extension to the compiler's macro handling
scheme.

When I started working on my monad implementation, I was in fact
looking for something much like macrolet, and if I had pursued that
approach I would have wanted symbol-macrolet just a bit later. Both
would be nice to have.

Konrad.

Adam Jones
2008-11-21 19:10:50 UTC
Permalink
As a first non-trivial exercice, I wrote an implementation of monads  
       http://clojure.googlegroups.com/web/monads.clj
The file contains the macro definitions, the definitions of three  
popular monads (maybe, list, state), and some illustrations of their  
use. Comments are welcome!
Since they support mzero and mplus, aren't these equivalent to
Haskell's MonadPlus? (i.e. they're a little more than *just* monads)
I'm trying to work my way through that material too, so I'm not
entirely sure. Either way, cool stuff.

I've been kicking around the idea of re-implementing Haskell
typeclasses on top of multimethods. Now that I think more about it,
this probably wouldn't be much work. The two big issues I can see are
ensuring incomplete instances can't be created and figuring out how
the dispatch function can work sanely. Haskell has an advantage here
in that the only thing typeclasses dispatch on is the types involved,
so it's trivial to not clobber any existing definitions.

-Adam
One thing I was wondering about: if I want to turn this into a  
library module, where could I place it in Java's namespace hierarchy?  
I don't have my own domain (and don't need one), and even though I  
could have it hosted somewhere (such as SourceForge), it doesn't look  
like a good idea to have the package name depend on a hosting site  
that might not be forever. How do others approach this problem?
Konrad.
Konrad Hinsen
2008-11-23 21:15:41 UTC
Permalink
Post by Adam Jones
Post by Konrad Hinsen
The file contains the macro definitions, the definitions of three
popular monads (maybe, list, state), and some illustrations of their
use. Comments are welcome!
Since they support mzero and mplus, aren't these equivalent to
Haskell's MonadPlus? (i.e. they're a little more than *just* monads)
You can define :plus and :zero if they are appropriate for a monad.
If they are defined, you can use them. None of the predefined monad
machinery will use them at the moment, but I plan to implement
conditions, which work only if :zero is defined.

In Haskell there are two different types of monads because of the
type system, but the Clojure implementation doesn't use the type
system at all, so :plus and :zero are simply used by convention.
Post by Adam Jones
I've been kicking around the idea of re-implementing Haskell
typeclasses on top of multimethods. Now that I think more about it,
this probably wouldn't be much work.
You need to find a way to store the type information with the data.
That is easy if you limit yourself to a specific data structure, say
a map with a key reserved for type information. But if you want to be
able to use typeclasses for general Clojure data (e.g. make sequences
an instance of Monad), I don't see a simple way to do it.

Konrad.
Adam Jones
2008-11-24 00:50:00 UTC
Permalink
Post by Adam Jones
Post by Konrad Hinsen
The file contains the macro definitions, the definitions of three
popular monads (maybe, list, state), and some illustrations of their
use. Comments are welcome!
Since they support mzero and mplus, aren't these equivalent to
Haskell's MonadPlus? (i.e. they're a little more than *just* monads)
You can define :plus and :zero if they are appropriate for a monad.  
If they are defined,  you can use them. None of the predefined monad  
machinery will use them at the moment, but I plan to implement  
conditions, which work only if :zero is defined.
In Haskell there are two different types of monads because of the  
type system, but the Clojure implementation doesn't use the type  
system at all, so :plus and :zero are simply used by convention.
Post by Adam Jones
I've been kicking around the idea of re-implementing Haskell
typeclasses on top of multimethods. Now that I think more about it,
this probably wouldn't be much work.
You need to find a way to store the type information with the data.  
That is easy if you limit yourself to a specific data structure, say  
a map with a key reserved for type information. But if you want to be  
able to use typeclasses for general Clojure data (e.g. make sequences  
an instance of Monad), I don't see a simple way to do it.
That's the problem I've been thinking on. I'm looking for a decently
sane way to build on the multimethod dispatch system here instead of
explicitly relying on types. The concept probably doesn't work very
well without a guaranteed unique method of identifying an object, like
a data type.

-Adam
Konrad.
Continue reading on narkive:
Loading...