CS Tantric bullshit
It is a good tradition of mine to waste my time with Haskell Monads while staying in Sri Lanka. Perhaps it has something to do with the historical Buddha, who taught to see things as they are, and the Orthodox form of Buddhism still preserved here, contrary to that diverse Tantric bullshit we could see in the motherlands of Buddha.
Time and again I am starting to read the supposedly seminal papers right from the horse's mouth, and each and every time I am literally getting sick and wanna puke just after a few paragraphs of this high-level, purely abstract wisdom of applied Category theory.
"Purity", lifting into a "higher dimensions", I remember reading similar crap in a highly elevated full of bullshit manuscripts of various grafomans about "pure abstractions", "universe of ideas" and merely "higher planes of consciousness". I had enough of that.
The very first phrase I have stumbled upon I would like to produce verbatim:
So here is another, more concrete way of looking at these “actions”: type IO a = World -> (a, World) This type definition says that a value of type IO a is a function that, when applied to an argument of type World, delivers a new World together with a result of type a
delivers a new World, holy fuck! together with a result of type a. This is worth of Hegel himself! And then they go on:
The idea is rather program-centric: the program takes the state of the entire world as its input, and delivers a modified world as a result, modified by the effects of running the program.
I have read Hegel's "Science of Logic" (in English translation) and a few Tantric books, so I am Jack's complete lack of surprise. For these pure abstractions guys it is perfectly OK to take the state of the entire world as its input, and deliver a modified world as a result.
The World is fed in on the left
while the new World, and the result of type a, emerge on the right
Days of reading The Indian Philosophy by Radhakrishnan rushed back to me. The absolute is unattainable to the conditioned by perception and language intellect alone due to the fact that perception (and hence intellect) are dealing only with the secondary effects and causes... OK, never mind.
Then I looked at the code, to see the handler by which these titans take the Whole World, but what I found was only a wrapping, similar to the unnecessary wrapping, which is using
\x -> x
instead of just
because primitive values are self-evaluating.
I looked for more code and found this:
sequence_ as = foldr (>>) (return ()) as
Yeah, this is exactly what I thought it is - a way to explicitly sequence evaluations in a lazy (with so-called Normal-Order of evaluation) language.
sequence is just a
(>>=) over a list of thunks (which perform procedure calls or whatever is wrapped inside)
sequence = return $ map (\a -> a >>= id)
But somehow this, being absolutely clear and obvious, does not type-check! WTF?
My fault is that I am too focused on syntax and semantics, like any Lisp programmer should be, and ignored the clue in the type annotation clutter (yes, finally, these are useful, for providing insights about function's behavior)
sequence :: [IO a] -> IO [a]
What is missed is that this
sequence function is already specialized for the
IO type, it is not completely generic, as a straightforward Lisp code would be, as I tried to read it, not merely unwrapping (what is the opposite of "lifting into a higher dimension?" casting down?) and performing of "actions".
Haskell is a strict, statically typed languages with an implicit parameter based polymorphism. It must know which instance of Monad it is, in order to select corresponding implementations of
return. Not only we have to satisfy the type-checker, but we must provide a concrete type for
the polymorphic type-constructor - which kind of Monad it is (similar to specifying which kind if a List it is).
Now lets state it again. A monad is a parameterized (polymorphic) abstract data type (an Interface) which is sufficiently defined by a couple of functions and a law (a set of rules which an implementation of these functions must obey).
To be a Monad is to implement an interface, which consist of two functions
return in such a way that the following laws hold:
(return x) >>= f ≡ f x m >>= return ≡ m (m >>= f) >>= g ≡ m >>= (\x -> (f x >>= g))
To ensure that Monads of the same kind are composable.
That's it. Nothing more. No Whole World lifting, no higher dimensions, just usual liberal arts "purely abstract" or "higher abstract mathematics" bullshit. Just a type-tagging of expressions (thunks) as "impure" and combinators of arity of 2, which take a typed thunk, evaluate it, and pass the result to a function, which wraps it using
return (which calls an appropriate data-constructor) into another thunk of the same kind of Monad, so the whole step or transition type-checks. The instance of Monad type-class provides the "concrete type" for values (thunks),
(>>=) encapsulates the implementation, and
return encapsulates the data-constructor.
This bullshit, for example, gave raise to the perfect shitstorm of blog posts about what a monad is really and esoteric monad tutorials by idiots.