[Haskell-cafe] Bool is not...safe?!
jo at durchholz.org
Sun Jul 8 08:28:04 UTC 2018
Am 08.07.2018 um 09:43 schrieb Paul:
> Hello again. Let’s talk about Haskell and not persons. I suppose that my
> not good English may lead to misunderstanding. Excuse me, in this case.
Nah, you are mixing up terminology that is easily looked up.
> If you allow me, I would like to show reasons why I said “imperative”
> and not declarative.
> In Haskell I can write:
> factorial 0 = 1
> factorial n = n * factorial (n - 1)
> I can call it: factorial 5 => 120.
> And often I meet in Web similar examples with note: “You see – Haskell
> is declarative language, it really looks declaratively”.
"It's declarative because it looks declarative" is a circular argument,
and misses whatever definition of "declarative" was actually used.
BTW you don't define it either. Arguing around an undefined term is
> We see principal difference:
> 1. In Haskell we map inputs (arguments) to result. In Prolog we define
> not mapping but *relation*, which is *bi-directional* while Haskell
> is *one-directional*, like C, Java, etc. We can find also arguments
> from result in Prolog.
Yeah, that's the defining feature of Prolog-style languages.
And where the pure subset of Prolog is conceptually different from the
pure subset of Haskell.
> 2. In Haskell like in any imperative language we describe exact
> algorithm/solution. We define *HOW*. In declarative language we
> define *WHAT*: we *restrict result* and don’t know actually how it
> will be evaluated.
> 3. In Haskell all is evaluated as you wrote code. Exactly. No magic.
Just as much or little magic as in Prolog.
Hey, FORTRAN's expression sublanguage was considered magic at the time
FORTRAN was written in all upper-case letters: You just write down the
expression, and the compiler magically determines what data to move
where to make it all happen.
So... "no magic" is not suitable as a criterion, because what's magic
and what's not is in the eye of the beholder.
Having written a Prolog interpreter, Prolog is as non-magical as C or
C++ to me; in fact I find Haskell's implementation slightly "more magic"
simply because I have not yet written a run-time for a lazy language,
but not *much* "more magic" because I happen to know the essential
algorithms. Still, Haskell's type system and the possibilities it offers
are pretty baffling.
> But in Prolog we restrict some *solver* to find answer (or answers).
Except in cases where the solver is too slow or goes into an endless
loop. At which point we start to mentally trace the solver's mechanisms
so whe know where to place the cut, and suddenly that magic thing turns
into a complex-but-mundane machinery.
> In the example this solver is called CLP(FD). Sure, there are other
> solvers. Modern Prolog systems contain a lot of solvers, expert
> system engines, etc, etc. So, Haskell has not solvers/engines.
> Prolog has. Prolog is DSL for solvers. Interesting analogue is SQL
> as DSL for RDBMS😊
> If we want to achieve the same magic in Haskell, we must write such
> solver explicitly (ie. “how”).
I got pretty disillusioned about Prolog when I tried to use it for
real-world problems. So I don't consider it much of a loss if you have
to code a solver if you want a solver.
> Another interesting speculation about real nature of Haskell is List
> monad. We often see “Haskell is declarative because it has backtracking”
Where did you see that claim?
Because at face value, this claim is hogwash. Haskell's semantics does
not have backtracking at all, and I doubt you'll find any runtime that
uses backtracking even as a mere implementation strategy.
> with attached some example of List monad/do/guard.
Which is unrelated to backtracking.
> But we can say that
> Python is declarative because it has permutations in its itertools
> module which allows to solve similar tasks.
Python is a language where even class and function "declarations" are
executable statements (making it really hard to work with
mutually-referencing declarations so this isn't a mere theoretical
quibble but a hard, real-life problem), and that's as non-declarative as
you can get without becoming totally useless.
I'm awfully sorry, but this is the most ridiculous claim I heard in a
I am even more sorry but I do have to talk about humans: Please get your
definitions right. It's easy, even if English isn't your native language
(it isn't mine either).
We understand that List
> monad is not backtracking, and “guard” is similar to Smalltalk “ifTrue”
> – no magic, no real backtracking.
Well if that example was hogwash, why did you bring it up?
But like Python itertools can be used
> to solve some logic tasks in bruteforce/permutations style (as many
> other modern languages with sequences, F#, for example).
Sure. You can to functional, pure, declarative, context-free etc. stuff
in imperative languages no problem. You can even do that in assembler -
large systems have been built using such approaches.
That doesn't make the languages themselves functional/pure/etc.; the
definition for that is that the language does not allow doing anything
that is not functional/pure/whatever.
Very few languages are really one of these properties, it's almost
always just a subset of a language; still we say that Haskell "is pure"
because the pure subset is very useful and in fact most programmers
avoid going outside that subset. (People rarely use UnsafeIO. Whether
_|_, or equality under lazy evaluation, are compatible with purity
depends on details of your definition of pure, some people would say
yes, some would say no.)
> You said that “imperative” term is based on term of side-effects. May be
> I’m seriously wrong, but please, correct me in this case. IMHO
> side-effects are totally unrelated to imperative/declarative
That depends on what you consider declarative.
I am not aware of any widely-agreed-upon definition, so you have to
provide one before we can talk.
> also I see
> main :: IO ()
> in Haskell.
As far as I know, the IO monad does not execute any IO. It merely
constructs descriptions of what effects to invoke given what descriptions.
The actual execution happens outside the program, in the runtime.
That's why UnsafeIO is unsafe: It triggers IO execution inside the pure
Haskell world, possibly creating impurities where the language semantics
assumes purity (IOW you may find that compiler optimizations may change
the behaviour of the program).
> When I was student, criteria
> of declarative/imperative was: functional, procedural, OOP languages are
> imperative, due to one-directional evaluation/execution and you code HOW
> to be evaluated, but declarative is bi-directional, you code relations
> (WHAT), between predicates and apply some restrictions.
That's Prolog's idea of "declarative".
HTML, CSS, and most Turing-incomplete languages are considered
Some people define "declarative" to be exactly the opposite of "imperative".
It's really a matter of definition.
More information about the Haskell-Cafe