
Non-determinism: a sublanguage rather than a monad - panic
http://okmij.org/ftp/tagless-final/nondet-effect.html
======
worldsayshi
Somewhat off topic: I'm very interested but as so often before with these kind
of texts I'm at least somewhat stumped by the terminology. I can _almost_ read
this and I've done two and a half ish courses of Haskell.

I've wasted so much energy feeling stupid when reading texts that I don't
understand. But most of the time not understanding is not about "intelligence"
but simply not having the right meaning assigned to the right amount of words.

You're not stupid, you just don't have enough structured data yet. I wish I
had that kind of insight and believed in it when I started out in university.
Not that I'm completely convinced even now.

~~~
mikekchar
I first learned Haskell so I could understand some of the papers I wanted to
read that used Haskell for examples. Even when doing so, I realised that I
would eventually have to learn ML, but haven't gotten around to doing it. I
think it's a bit like literary researchers who have to learn ancient Greek or
ancient Chinese to get to the bottom of things.

It's funny that when I grew up I was always praised for being clever, so I
never once doubted it. However, when I chose to learn Japanese and moved to
Japan, suddenly many people assumed I was stupid -- because I could never
quite understand what was going on. It's been an interesting experience. Which
is it? Am I clever or stupid?

Eventually I've come to the point: clever or stupid makes no difference. The
only important things to ask are, "Do I understand" and "What do I need to do
to understand". It's also made me realise that relying on my supposed
cleverness has actually been a source of problems in my life that I had not
thought about before (because I'm clever and clever is good, right?)

~~~
bojo
It's interesting to read this comment because I experienced nearly the same
thing. Thought I was clever because everyone told me it was so, was admittedly
quite arrogant about my technology skills, learned Japanese, moved to Japan,
and could barely explain anything to my programming peers at the level of a
five year old.

It took several years of forced humbleness to erode the arrogance, stop
thinking I was so clever, and simply apply myself to the task of learning the
necessary Japanese to explain myself correctly.

What I generally see with people new to learning Haskell (or similar) is that
they approach it with their bag full of imperative language cleverness, and
find the concepts and terminology hard to grasp because they refuse to become
humble for a bit and examine it as a paradigm different from the one they
know.

To be fair I was no different until I finally started understanding it, but
looking back, learning Haskell was similar to my Japan experience. It became
much easier once I buckled down, learned the parts that didn't make sense, and
most importantly began applying them.

------
panic
If you like this article, the rest of Oleg's stuff on this style of embedded
DSLs is also worth reading: [http://okmij.org/ftp/tagless-
final/index.html](http://okmij.org/ftp/tagless-final/index.html)

One particularly cool (and surprising, to me at least) trick is defining
interpreters that carry out composable optimization passes on a DSL without
needing an intermediate representation: [http://okmij.org/ftp/tagless-
final/course/optimizations.html](http://okmij.org/ftp/tagless-
final/course/optimizations.html)

------
lmm
The trouble with this style is that your sublanguage program is no longer a
value, so you can't reason about it or treat it as one. Instead you've
created, effectively, an imperative method that accepts a bunch of callbacks
that implements effects and runs those.

I mean, the imperative programmers already knew they could write programs full
of effects without monads. But there's a reason we regard that as bad style.
As far as I can tell this piece is just a longwinded reinvention of imperative
programming?

~~~
panic
Yes, the program is written in terms of callbacks, just like monadic programs
are written in terms of "return" and "bind" callbacks. This style isn't any
more imperative than monadic programming. You could port this code to Haskell
(using typeclasses instead of modules) and it'd work just as well.

~~~
lmm
Tagless final style programs are indeed written in terms of "return" and
"bind" callbacks, but programs written with "vernacular monads" or free
coproduct style aren't - they're plain old values and can be inspected as
such. That's the style I prefer.

------
alphaalpha101
Thank god. I've felt like we've been getting closer to breaching the peak of
the hype curve for what I'd probably call 'monadic pure functional
programming' i.e. Haskell, Scalaz, etc. It'll have its hardcore advocates
forever, of course, but I think we might be finally getting to the point where
people realise 'wait this sure is an absurd amount of complexity to represent
some fairly simple functions, surely there must be a better way?'.

~~~
tathougies
I don't understand this comment, almost every compiler and language in
existence uses monads for computation. Monadic sequencing is the foundation of
almost every CPU. Most languages are utterly dependent on them.

Haskell and other pure languages let you compute values independent of the
monad its computed in, which is very useful. Of course, this is all
conceptual, eventually everything is translated to underlying CPU monad and
its implicit join.

~~~
Veedrac
> Monadic sequencing is the foundation of almost every CPU.

What on earth are you modelling a CPU as? What thing a CPU does corresponds to
join?

------
graphememes
Honestly I feel like Haskell and OCaml are severely over-engineered and overly
focus on nuance far too much these concepts and ideas can be expressed in a
more concise and legible manner in mathematical notation than the programming
languages used as examples here.

~~~
wyager
Haskell is an incredibly simple language with only a few core constructions.
You have ADTs/pattern matching and lambda abstraction/application and that's
basically it. Everything else in the standard language is (usually
straightforward) syntactic sugar around those two concepts. This includes the
vast majority of data structures, monads, etc. All the other things that
people use exist as (individually) extremely simple extensions that you can
learn in isolation in a few minutes.

Haskell is possibly the least over-engineered language out there; it's almost
as if laziness (no pun intended) was a guiding principle when building the
language.

Ocaml is more complicated, but I'd still consider it vasty simpler than C++ or
Java (as long as you ignore ocaml's object layer).

~~~
Volt
If Haskell is so simple, why is GHC so big?

I see your claim repeated often on HN, but I think it's disingenuous.

~~~
tathougies
A compiler takes one language (usually higher level) and transforms it into
another (usually lower level). GHC, like C, go, or rust compilers, compiles to
assembler, a very low-level and complicated language.

One would expect that a system to transform a simple high level language into
a complicated low level language would would grow proportional to how simple
and high level the source language is. Thus, a very simple, high-level
language ought to have a larger compiler than a more complicated, lower-level
language.

Indeed, we see this in real life. Writing a haskell compiler is a fairly big
undertaking whereas a C compiler could be written in a few days. This is
because C is complicated, but low-level, and Haskell is simple, but high-
level.

Let's not confuse the simplicity of translation with the simplicity of
semantics.

~~~
qznc
I believe a toy Haskell compiler could be made with comparable effort to toy C
compilers. Admittedly, I cannot find people making toy Haskell compilers.

What makes Haskell higher-level than C? Garbage collection does not really
complicate the compiler if you just use BoehmGC.

You can use a simple subset of assembly instead of the full complicated set.
Toy C compilers do this, e.g. by treating x86 as a stack machine.

