Monday, June 17, 2013

Thoughts on Kleisli Arrows in Java (WIP)

Here are some ramblings as I puzzle my way through on how to represent Kleisli arrows in Java (and why I would want to do that, anyway). This is very much a work in progress, so no solid conclusions from this posting.


Categories are abstractions. They have objects and morphisms. The thing of Category theory is that the objects can be anything, as they are atomic, and the morphisms aren't necessarily functions. So, the objects can be numbers, not that we care, or they could be arrows (another term for morphisms), or they could be categories themselves, so the morphisms become morphisms between categories. Or if the objects are arrows then the morphisms are higher-order functions.

Neat-o!

So, John Baez did some wonderful pieces on higher-order categories in the direction of physical math: topologies and groups and such, and this was replicated in Edward Kmett's work with ... what are they called? Ah, yes: semigroupoids (how could I forget), where the monoids have no zero bases and so identity functions aren't necessary, I suppose.

Interesting! Half-monoids!

But if we look at Categories as simply that: objects and morphisms, and we look at morphisms as simply arrows from a to b, then does that simplify my implementation of my categories library?

Monads no longer are generically typeful but now use inheritance to describe the type families:

Monad<a> is the interface and Maybe<a> extends Monad<a> instead of

Monad<M extends Monad, a> being the interface as Maybe<a> extends Monad<Maybe, a>.

The problem is in the generic functions, how does one grab the 'm' in the monadic type? Or is it as simple as using inheritance and forgetting the thorny problem of genericity, or passing that problem off to the inheritance structure?

Same thing for Arrow ...

instead of Arrow<a, b, c>

we have Arrow<b, c>

and then the Kleisli arrow becomes more simple, perhaps? Because

KleisliArrow<m, b, c> extends Arrow<b, m c>

... but how does that work? Can it work? I don't see how that works.

for first :: a b c -> a (b, d) (c, d)

how does that work for the KleisliArrow, and for chaining the monadic computation?

It appears further research is necessary for me to get a solid grasp of this to be able to implement this properly in Java (as opposed to writing a haskell parser on top of Java, which is also a viable way of going about it, except for the fact that there is political resistance to learning a domain-specific language from devs brought on to code 'only' in language-of-choice X).

So that's my problem, because in my 'Monads in Java' article I concluded with a:

So you see we can now do the following:

f.apply(m).bind(g).bind(h)

and I now know that f.apply(m) is a weakness in coding. This should all be strung together with Kleisli arrows and the resulting morphism be run through the Kleisli computer.

"The (explicit) use of apply considered harmful"?

I mean, Gah! How bold! How daring! How so against the grain!

And it isn't even really 'harmful' either. More like obtuse or obnoxious. And not even that, more like: inelegant. That's the word: inelegant. And we're not even 'using' apply in the above computation. I mean, we are, but we are always using apply. It's so inherent that now just juxtaposition is now apply, so it's not the '(explicit) use' of apply, it's the '(explicit) call' or '(explicit) invocation' of apply that's inelegant.

I mean, when I see the above formulation, I now shudder, whereas before I might've said, with a pause so slight it didn't even register, 'What do we do here? Oh, use apply!' knowing, at the back of my mind, that this didn't sit perfectly right, but what else was there to do?

Well, with Kleisli composition, there is nothing to do at all, but just do it

runKleisli (f <+> g <+> h) m

and we're done.

Now, how to represent that in Java, ... well, I do have a KleisliArrow type that does return the underlying arrow, but what about composition ... it probably has that, too:

f >>> g >>> h

But the gnawing problem there is that KleisliArrow is not related to Arrow, because, properly, it isn't: KleisliArrow on a specific monadic type m IS related to Arrow.

And I don't know how to represent that in Java.

Yet.