<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
  </head>
  <body text="#000000" bgcolor="#FFFFFF">
    <p>Hello Bryan!<br>
    </p>
    IMHO a discrepancy arises from the to different flows:<br>
    <br>
    <ul>
      <li>With pattern matching we create 2 branches with <b>data flow</b>
        (typical for ML):</li>
    </ul>
    <blockquote>
      <ol>
        <li>Result exists - to be processed (head of list)</li>
        <li>Result does not exist, nothing to process (no head at whole)<br>
        </li>
      </ol>
    </blockquote>
    <ul>
      <li>With boolean testing we create 2 branches in <b>logical flow</b>
        (typical for Prolog):</li>
    </ul>
    <blockquote>
      <ol>
        <li>Predicate is true and further sequential processing is
          possible</li>
        <li>Predicate is false and other part of the sentence is false
          too (no more further processing)<br>
        </li>
      </ol>
    </blockquote>
    So, my misunderstanding is that I try to think about ML/Haskell as
    about declarative languages, but they are imperative.<br>
    <br>
    <div class="moz-cite-prefix">05.07.2018 20:51, Bryan Richter wrote:<br>
    </div>
    <blockquote type="cite"
      cite="mid:55e21eb7-0e6c-699d-05fa-51b7a5eef773@chreekat.net">
      <pre wrap="">Happily, all of this has nothing to do with monads or Haskell's
special syntax for monads. :)

I would not call it static-types fanaticism, but rather,
pattern-matching fanaticism. To me, "boolean blindness" is a cute way
to describe how this:

    -- | Sum the first two ints of a list, if possible
    foo1 :: [Int] -> Maybe Int
    foo1 (x:y:_) = Just (x + y)
    foo1 [x] = Just x
    foo1 [] = Nothing

is better than this:

    -- | Same thing, but with "blind bools"
    foo2 :: [Int] -> Maybe Int
    foo2 xs =
        if length x >= 2
            then Just ((x!!1) + (x!!2))
            else if length x == 1
                then Just (x!!1)
                else Nothing

NB: I already had to correct one mistake in that second code while
writing it, and there may be others (I forget if it's (!!) or (!), and
I also forget if it's 0-based or 1-based).

The first is a description of what I want. It is correct by
construction.

The second requires converting the description of what I want (sum of
the first two ints) into a description of how it is computed, with
steps like "find the length and compare it to 2".

By using pattern matching, I get both a guarantee of the structure I
need, as well as information from within the structure at the same
time. With an operational description, I have to do it in separate
steps.

To me, that's the crux of boolean blindness: Use pattern matching
whenever possible!


On 07/05/2018 11:04 AM, PY wrote:
</pre>
      <blockquote type="cite">
        <pre wrap="">So, the problem is that test of emptiness does not force you to something right. And possible errors are:

    if empty:
      # do if NOT empty - BUG!
    else:
      # do if EMPTY - BUG TOO!

    or

    # do if NOT empty - BUG!
    if NOT empty:
      # now nothing or old "do if NOT EMPTY"


OK, I understand it. But how is it related to Booleans? :) Sure, if you use Maybe or Either you are forced with nature of ">>=": it cuts off incorrect branches. With if-then - it does not. But it's not
related to Bool: Bool is result for predicates. Maybe/Either forces you with magic operation ">>=" (which is hidden by do-sugar). Bool does not force you - right. But it's problem of Haskell
implementation. For example, Prolog "forces" you:

Haskell forces you in monad "do":
  do
    someInt <- someMaybe
    -- will not be executed if someMaybe is Nothing

Prolog forces you too but on success/fail (Boolean?):
  someGoal, anotherGoal   % anotherGoal will not be executed if someGoal is False

Haskell adds only "bool" function which is close to ">>=" in terms of it hides semantic of right bool's processing, avoid those possible errors. If you will use "bool" anywhere when you use Bool as
result - all will be fine, or? Sure, you can move "head" usage out of "bool" but you will get empty "bool"s argument. So, IMHO examples of problem with booleans is not related to Bool type at whole,
but related to problem that Bool has kind * but not * -> * to be processed in monadic style (and to has needed  ">>=" semantic to force you).

OK, but original article was not about Haskell's monads, but about Bool in general :)    Also what I can't understand: if we will think in such manner does it mean that "if..test" construct is
"boring"/"blindness" (excuse my English:) at whole? And all predicates must be removed from the language? What will happen to `filter` function without predicates? And no way to avoid "if..else"
construct and predicates functions.

As for me, this question is related to static-types fanaticism and "How many angels could dance on the head of a pin". Example with "head" is totally incorrect - it can deconstruct list and no need to
predicate function. But what I should do with isSpace, isLower, etc? How to use predicates at whole? :)   To map   a -> Bool   to   a -> Maybe a  ?
What about function which returns IO Bool? Action which can ends with non-critical failure (and need optionally logging, for example) ?


05.07.2018 17:27, Stefan Monnier wrote:
</pre>
        <blockquote type="cite">
          <blockquote type="cite">
            <pre wrap="">There is an opinion that Bool type has problems. It's "dangerous", because
it's not good to be used as flag for success/fail result. I read this post:
<a class="moz-txt-link-freetext" href="https://existentialtype.wordpress.com/2011/03/15/boolean-blindness/">https://existentialtype.wordpress.com/2011/03/15/boolean-blindness/</a> and was
shocked. How popular is such opinion? Is it true, that bool is "bad" type?
</pre>
          </blockquote>
          <pre wrap="">To me the argument boils down to the `head` case mentioned by Alex.

Most programming languages force you to write code like

    if List.empty l then
        ...
    else
        ... x = List.head l ...

where the problem is that the fact that the List.head call will find the
list non-empty is not obvious (in the sense that it requires reasoning).

In contrast

    case l
    | nil => ...
    | cons x xs => ...

makes it trivially obvious that `x` is extracted from a non-empty list
without any reasoning needed at all.


        Stefan

_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
<a class="moz-txt-link-freetext" href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe">http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe</a>
Only members subscribed via the mailman list are allowed to post.
</pre>
        </blockquote>
        <pre wrap="">


_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
<a class="moz-txt-link-freetext" href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe">http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe</a>
Only members subscribed via the mailman list are allowed to post.

</pre>
      </blockquote>
      <pre wrap="">

</pre>
      <!--'"--><br>
      <fieldset class="mimeAttachmentHeader"></fieldset>
      <br>
      <pre wrap="">_______________________________________________
Haskell-Cafe mailing list
To (un)subscribe, modify options or view archives go to:
<a class="moz-txt-link-freetext" href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe">http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe</a>
Only members subscribed via the mailman list are allowed to post.</pre>
    </blockquote>
    <br>
  </body>
</html>