Thanks all for your answers!
I know that this is not that important, but just for the sake of discussion, let me provide an example:
consider a datatype
data ShouldShow
= Show
| Hide
if we want to consume a value shouldShow
of that type, the most Haskelly way to do it is to use pattern matching
case shouldShow of
Show -> ...
Hide -> ...
I would say that such a code would read better if it was written like
if shouldShow then ... else ...
but that is not possible. The best we could get in that direction is to use a toBool :: ShouldShow -> Bool
function and have
if toBool shouldShow then ... else ...
I would argue that the toBool
before shouldShow
does not help neither the writer nor the reader of the code, but it is there just to please the type checker.
The same this happens whenever you have a newtype over Bool
.
This is not a big deal, but it’s still a little annoying.
There I thought about generalising the if
statement so that it could accept something which could be turned into a boolean.
The idea is not to have instances for anything and introduce a concept of truthiness like you have in dynamic languages. I would have instances basically only for types with cardinality 2 where their meaning is clear. @maxigit I would not have Boolish a => Boolish (Maybe a)
, or Boolish String
or Boolish Int
@BurningWitness, it wouldn’t be an implicit cast, but explicitly defined by the instance definition. So @ApothecaLabs there would be no confusion between isTrue
and notFalse
; If a value get eveluated to True
, it goes to the then
branch, if it evaluates to False
, it goes to the else
branch