[Haskell-cafe] Bool is not...safe?!

Paul aquagnu at gmail.com
Sun Jul 8 07:43:30 UTC 2018

@Olaf Hello, you are right. Prolog allows side-effects, which means that you has predicates which is not “pure”. Today, after “pure” functional programming fashion, there is fashion of pure declarative programming too 😊 You define nature of predicates with determinism categories but “variables” nature with +/- notation (if variable is “output” only then it’s not pure predicate, for example, “X is Y + 5” is not pure because it’s functional but not declarative, ie, it’s evaluation but not relation). Mercury has “!” annotation, which is close to linear types I suppose (am I right?). Idea was side-effects is coded as input-output variable which is changing (state of external world). Unfortunately, I learned Prolog when I was student...  

When we are talking about truth, probably truth, etc, I think we mean https://www.mercurylang.org/information/doc-latest/mercury_ref/Determinism-categories.html. In Prolog we apply restrictions/relations to answer to get more strict answer. It’s linked with declarative nature: no evaluation but some kind of DSL to barrier answers. Sure, it’s not strict definition or something like this 😊 My intuition is like Prolog evaluation can be imagine in Haskell terms like some logic monad on top level instead of IO monad (main :: SomeLogic (), for example). Btw, how works Curry? And another my intuition is that it’s possible in Haskell with some (new?) monad. I will observe your examples, thanks a lot!

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. 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”. IMHO it looks only (you can check Erlang syntax, which is similar to Prolog even, but Erlang is not declarative language). Let’s try the same in Prolog.

factorial(0, 1).
factorial(N, F) :-
        N #> 0,
        N1 #= N - 1,
        F #= N * F1,
        factorial(N1, F1).

I can call it: factorial(5, X) => X=120.
But also: factorial(X, 120) => X=5.

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.
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. But in Prolog we restrict some solver to find answer (or answers). 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”).

Another interesting speculation about real nature of Haskell is List monad. We often see “Haskell is declarative because it has backtracking” with attached some example of List monad/do/guard. But we can say that Python is declarative because it has permutations in its itertools module which allows to solve similar tasks. We understand that List monad is not backtracking, and “guard” is similar to Smalltalk “ifTrue” – no magic, no real backtracking. 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).

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 “dichotomy”. For example,

int sum(int a, int b) { return (a + b); }

I don’t see here side-effects. I have not problems to write all my C code in such style. Without any side-effects. Also I find “pure” functions in D language, “function” keyword in Pascal and Basic. But also I see

main :: IO ()

in Haskell. So, I don’t think side-effects are relative to declarative/imperative dichotomy at whole. 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.

I am surprised that there is another classification: based on side-effects. Please, correct me, where I’m wrong and if you can do it without such emotion – I will be very glad to get new knowledge.

PS. Out of scope is declarative DSLs written in imperative languages: like Scons Python build system. Sure, there are a lot of similar Haskell libraries/tools. IMHO more correct is to say “Scons has declarative Python-based DSL, but not Python is declarative itself”.

From: Joachim Durchholz
Sent: 7 июля 2018 г. 11:17
To: haskell-cafe at haskell.org
Subject: Re: [Haskell-cafe] Bool is not...safe?!

Am 07.07.2018 um 07:15 schrieb Paul:
> By the way, there are a lot of articles why checked exceptions are bad 
> design (more problems than benefit).

That's because exceptions disrupt control flow.
If they're used as an alternative to pattern matching, i.e. thrown only 
in tail position and always either fully handled or rethrown unchanged, 
then they're fine.

I.e. checked exceptions are bad because they make it easy to construct 
bad design. Unchecked exceptions can be abused in the same way but there 
seem to be psychological reasons why this isn't done so often.

> More interesting for me is this snippet:
> case (action :: Either err a) of
>     Right result -> ...
>     Left err -> deal_with err
> Somebody says me that to use Bool in such way is “not safe” because no 
> way to know what does “True” returning from “action” mean. Success or 
> failure? But with some ADT (Success|Failure) code is more Haskellish and 
> safe.

Terminology N.B.: (Success|Failure) is not an abstract data type (ADT). 
It's pretty much the opposite of abstract.

> But is it true? We are talking about semantics, not type-safety because 
> type-checker passes both cases (positive branch under False/Failure, 
> negative branch under True/Success). But the same with Right/Left: 
> nothing says you to use Right for positive and Left for error case. Is 
> it true?

There's no good way to use Bool as the type of action, so the point is moot.
Of course you can reconstruct action's type to be a struct consisting of 
a Bool, a SuccessResult, and a FailureResult, but that's just awkward so 
nobody is doing this.

> Bool is algebra <1, 0, +, *>

Let me repeat: the algebraic and mathematical properties of Bool are 

> Problem with Haskell is that it’s imperative and not declarative 
> language.

Haskell isn't imperative.
I.e. it matches almost none of the definitions for "imperative" that I 
have ever seen.
It matches a substantial percentage of the definitions for "declarative" 
actually, but not enough of them that I'd instinctively say it is really 
declarative - others with a different set of definitions encountered may 
feel differently.

> The root of the problem is that imperative nature of Haskell leads to 
> missing term “evaluation to something”.

The most compact definition of "imperative" that I have seen is 
"computation progresses by applying side effects".
By that definition, the ability to distinguish evaluated and unevaluated 
expressions is irrelevant.

> Haskell program is not evaluated
> expression and in the same as in Java or C: it is IO action. But in 
> Prolog every piece of code is evaluated to TRUTH or to FALSE. Each 
> sentence is a goal which can be achieved and becomes a fact or can not 
> be – and becomes lie.

Wrong terminology. Nothing in a computer is a lie.

Prolog works by turning stuff into either tautologies or contradictions.
A lie is something entirely different: a statement that intentionally 
contradicts reality. Programming language semantics does not have 
intention; programs may have state that matches or contradicts reality, 
but take this message which isn't a lie but still does not match any 
reality because no sheet of paper with these glyphs ever existed (there 
may be in the future if somebody prints this message, but that doesn't 
turn this message from a lie into a truth).

Please, get your terminology right. If you keep working with "almost 
right" terminology in your head, you will continuously "almost 
misunderstand" whatever you read, leading you to conclusions which are 
almost right but take a huge amount of effort to clean up. People who 
know the concepts and the terminology will find it too tiresome to talk 
with you because it is all about educating you (which is not the right 
level to talk with a person anyway), and will eventually drop out of 
discussions with you; the only persons who talk to you will be those who 
happen to have similarly vague ideas, placing you in an echo chamber of 
ideas that lead nowhere because everything is subtly wrong.
Just saying. I'm not going to force anything on you - but I find that 
this message is entirely about terminology correction and almost nothing 
about the topics that really interest you, which means it's been mostly 
a waste of time of both of us.

Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
Only members subscribed via the mailman list are allowed to post.

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20180708/6a03df29/attachment.html>

More information about the Haskell-Cafe mailing list