9

The following does not work, for obvious reasons.

(defprotocol Monoid
  (mappend [a b])
  (mzero []))

mzero has zero arguments, and zero argument methods are not allowed (or do not make sense) in protocols. In Haskell or Scala, where the dispatch is type-based rather than value-based, this is not a problem.

What would be the correct way to conceptualize and write Monoid protocol in Clojure?

missingfaktor
  • 90,905
  • 62
  • 285
  • 365
  • why do you need it to be a protocol rather than a module? if you are expecting different implementations then how would haskell infer which implementation is required in a particular use case? (i think it's a good question, i'm just trying to chase down the issue involved). – andrew cooke May 26 '12 at 17:58
  • 1
    @andrewcooke Haskell infers based on the static type at the use site. The method that is called is resolved statically. – Don Stewart May 26 '12 at 18:31
  • @andrewcooke, what would module mean in the context of your statement? – missingfaktor May 26 '12 at 18:34
  • @missingfaktor - what i said was wrong. what i should have said is that `mappend` would be in the protocol, but the equivalent of `mzero` would be a function that creates an implementation of that protocol (and lives in a namespace - module - with the implementation). what i am missing, from the above, is how something like `mzero` can be implied by context *separately* from a particular implementation. – andrew cooke May 26 '12 at 18:51
  • @andrewcooke, this example might help to understand how this works in Haskell: http://ideone.com/j1nnz. – missingfaktor May 26 '12 at 18:53
  • I heard new Reducers library has monoids, so I suppose there exists some way to encode this in Clojure. :-) – missingfaktor May 26 '12 at 18:55
  • http://clojure.com/blog/2012/05/08/reducers-a-library-and-model-for-collection-processing.html [for reference for others] also, i am going to delete some of my questions above because it's just noise. – andrew cooke May 26 '12 at 18:58

1 Answers1

5

looking at the source, the way that this is implemented in the new reducers library is not as a procotol but an overloaded function. a no-args call is mzero; two args call is mappend.

more exactly, monoid takes two arguments - op and ctor and returns a function which, when called with no arguments, evaluates ctor, and when called with two, delegates to op.

this is consistent with how zero is handled in a fold, for example - reduce (fold) will evaluate the function being folded with no args to find the zero, if necessary.

i feel a bit ashamed to show something so unexciting, but i don't see how you can do better within clojure. thanks for the explanations/education in the comments.

andrew cooke
  • 45,717
  • 10
  • 93
  • 143