What about NonEmpty
?
I’m not sure what you mean.
I suppose you could add a warning,
like was done with head and tail.
Yes, I think if max
/minimumMaybe
are added then it makes sense to add a warning to max
/minimum
.
λ> maximum []
*** Exception: Prelude.maximum: empty list
NonEmptyList
would not explode at run time (I understand there are other problems with this). It would be a classic “parse, do not validate” moment.
I’m still not sure what you mean and I’m not sure if you’re even responding to me! But if you are, then I guess I can elaborate: the problem with max
/minimum
is not that they’re partial on all Foldable
instances but that they’re partial on some.
Am not a fan of such warnings, unless they are disabled by default. The head/tail warnings are even less useful, since the ‘error’ is a fundamental property, not a bug.
Yes, I’m not sure if adding warnings would pass CLC vote, but I’m almost certain adding max
/minimumMaybe
would.
It’d be better if the warning system could add warnings to specific instances. I don’t think it can currently and I couldn’t figure out how to work around it.
It’s not a problem with specific instances. The instances for which it’s safe can have Foldable1
instances too, and they should use max
/minimum1
, which has a constraint on that type class. (However, I don’t think max
/minimum1
exist where Foldable1
is defined, so there’s a hole in the ecosystem there.)
For now, I suggest only the smallest set of changes needed to avoid:
…thereby alleviating the need for extra “special” classes like PartialEq
and PartialOrd
.
Why so cautious? Because Haskell usually has no notion of evaluation order e.g. (x + y) == (y + x)
, so (+)
should be commutative…and unfortunately, not (always) so for floating-point values:
So that “large pile of floating-point changes” would require careful scrutiny (and the time to do so) to determine which of them are “Haskell-compatible”.
Perhaps the design of the R language (which is also nonstrict) could prove useful in such a task.
It’s more about what can we do to incrementally evolve Haskell without breaking anyone’s code and making things nicer for everyone. I do feel like we’re maybe talking past each other, but that’s ok.
I agree with several of the things already said. Things like getting Text
in place of String
, vector
, the idea of a better situation around Show
, and more.
There is one idea that I haven’t seen mentioned:
A named version of every operator.
Purescript does this, actually it is enforced, and it would be great for us to steal that idea at least for base
. It is very helpful when talking about code, be that pair programming, or something else.
If you do make |>
and <|
the obvious definitions of one-side <|>
, they end up being cons
and snoc
. Something to that…
containers
already defines both of those operators, with precisely those meanings!
Sounds like a lock then!
(|>) :: Alternative f => a -> f a -> f a
a |> fa = pure a <|> fa
(<|) :: Alternative f => f a -> a -> f a
fa <| a = fa <|> pure a
This is in my fantasy base
, along with an additional rule:
Class should define named functions, and operators should be defined separately
-- Like this:
class Semigroup a where
append :: a -> a -> a
(<>) = append
-- Not like this:
class Semigroup a where
(<>) :: a -> a -> a
The Num
class is a particularly bad offender as well.
The intent is to make it easier for small operators like +
and *
to be re-used, instead of inventing operators like |+|
or monsters like <<*>>
. It is a lot easier to hide (conflicting) operators when they aren’t a part of a class definition.
I actually disagree with that. I understand that a name is usefull to communicate with others but I see most operator as syntax and pretty much never need their name when I read an expression with operator.
For example in C++ in object->method(a,b)
I don’t need a name for ->
, (..)
and ,
. I just read it.
It is the same with Haskell construct like (,) <$> a <*> b
. I just SEE what it does (even though now a day I prefer to use liftA2 (,)
. Having names in my head will just confuses me.
That only works if you see operators as syntax.