Wednesday, August 05, 2015

Using Ruby to Inject you a Monoid

A monoid has an append operation (like plus) and an identity (like 0) and you get for free a concat operation.

In Ruby it's something like:

[1,2,3].inject(0) {|a, x| a + x }
=> 6

Or just, [1,2,3].inject(:+)

In Haskell, you can even see it in the type signature for Monoid:
mconcat :: [a] -> a

You can see the array on the left ([1,2,3]) and the result unpacked (just 6).

What if you want to take it up one level of abstraction and have any operations on your list of numbers.  You just use a different monoid called Endo.

To take it to this next level you need a more abstract append and identity.  

Append needs to combine two operations:
compose = -> (f,g,*args) { f.call(g.call(*args)) }

And identity just returns what you give it:
id = -> (x) { x }

Which lets you then write:
[->(x){x + 2}, ->(x){x * 7} ].inject(id) {|x, y| compose(x, y) }.call(8)
=> 58

Or in Haskell:
Prelude> let a = foldr (.) id [(+2), (*7)]
Prelude> a 8
58

See:




Tuesday, February 17, 2015

jQuery still not a Monad

I read jQuery is a Monad and thought yeah this is pretty cool I finally understand Monads.

jQuery is not a Monad, a Monad can take any type and it has a join operator that takes a doubly wrapped value and turn it into a singly wrapped one. This means that for it to be a Monad jQuery would have to work on any type, you have to be able to give it a String, Int or DOM and it operates on it consistently. jQuery's .map can only deal with the one type. It does have jquery.map but that would make the Array the Monad (or actually just a Functor) not jQuery.

Many of jQuery's method are specific to DOM manipulation, parsing and the like and not related to Monads in anyway - more like a combinator library like HXT.

The idea that it is a Monad still continues with, What jQuery can teach you about monads and Does jQuery expose a monadic interface?. One of the points that I think people ignore is that JavaScript has an implicit this and it affects how you apply function:
As is common with object-oriented language implementations, the this variable can be thought of as an implicitly-passed parameter, so we can then look through the API for a jQuery container looking for a method that takes one of these transformation callbacks and returns a new jQuery container.
This actually prevents you from easily (and definitely not clearly) writing Moands in JavaScript, Monads in the generic fashion that is required:
So, is jQuery or the Django ORM a monad? Strictly speaking, no. While the monad laws actually hold, they do so only in theory, but you can not actually use them in those languages as readily as you can in, say, Haskell. Methods get the object as the first (implicit, in JavaScript) argument, not the value(s) stored in the object. Methods are not first class objects independent from their classes. You can circumvent those restrictions by implementing some boiler code or, in Python, metaclasses that do some magic. What you get for doing that is a much easier time writing functions that work on all monadic classes, at the expense of making the whole concept more difficult to understand.
As Ed said: "jQuery is an amazing combinator library, but it isn't a functor, it isn't applicative, and it isn't a monad."