RFC: Add HasCallStack constraint to partial Data.List functions.

Hécate hecate at glitchbra.in
Wed Jun 9 08:44:05 UTC 2021


But nothing prevents us from agreeing on restricting the semantics of  
`IsPartial` !

We can write down in the Haddocks “`IsPartial` should exclusively be 
used for functions that use error/errorWithoutStackTrace, and not for 
imprecise exceptions or asynchronous exceptions.”
We have documentation, guides, tutorials, comments, style guides, etc. I 
just don't understand why it is a problem. And again, this is not a 
discussion that is unique to us.
The PureScript community have had their own Partial typeclass for ages 
and this hasn't triggered the end of the world. We don't have to delve 
into year-long arguments on The Nature of Partiality.

--- rant ---

As a general comment, it is honestly appalling how RFCs like that 
trigger such circlejerks that are so utterly disconnected from reality. 
This does not make us better as a community.
The last time I suggested a change in the base library (up-streaming 
strictness optimisations that were enabled at the first level of 
optimisation),
I've was told that this went against the spirit of the language, even 
though a simple look at the most minor optimisation level would reveal 
that we haven't been "true" to this "spirit" for a long, long time.

And this is extremely bizarre since we try to take the highest moral 
stances on some topics whilst making dirty compromises on other topics 
(for which I am not seeing anyone actively try to change the status quo).

 > It's been well known for close to three decades(!) that it is perfectly
 > possible to add sophisticated debugging support to lazy languages like
 > Haskell without impacting on the language semantics or formulation of
 > its libraries. The existing tracing and profiling mechanisms of GHC
 > are examples of this.

Henrik, Debug.Trace functions requires the use of "unsafePerformIO". Is 
this really the sort of thing we want to promote when we talk about 
"sophisticated debugging support to lazy languages without impacting the 
semantics"?
Looks like the semantics of pure functional programming are flushed down 
the toilets with that one.

Regarding profiling, we are *unable* to teach how it works. The Haskell 
Wiki article¹ is a stub, there are issues² on the Cabal bug tracker to 
ask how to enable it, and for most people it's still a mystery.

So before we say things like "It's been well known for close to three 
decades(!)(sic)", I suggest we get our shit together because right now 
we look like a bunch of clowns. And if by any chance the University of 
Nottingham has a secret vault of forbidden techniques regarding 
profiling Haskell applications, I'd love that the rest of the community 
could benefit from this 30yo knowledge, since apparently nothing has 
filtered and we are still like monkey playing with sticks in the outside 
world.

So let's meditate on this a bit, shall we? As much as I am not the 
biggest fan of ad-hoc typeclasses to signal operational behaviour, the 
inability of the community to promote the "better" ways to handle such 
failure modes makes me think that we have no right to spit on this RFC.


---
¹ https://wiki.haskell.org/How_to_profile_a_Haskell_program
² https://github.com/haskell/cabal/issues/5930

Le 09/06/2021 à 09:57, Julian Ospald a écrit :
> I'm aware what was meant, but this was in response to the proposed 
> 'IsPartial' typeclass, which will have this confusion pop up more often.
>
> On June 9, 2021 7:48:58 AM UTC, "Hécate" <hecate at glitchbra.in> wrote:
>
>     Let's not diverge too much on the nature of IO functions, in the
>     context of this conversation, here are the functions that are partial:
>
>     - head, tail, init, last, ...
>     - foldr1, foldl1, maximum, minimum, ...
>     - (!!)
>
>     They all have in common the usage of `error(WithoutStackTrace)`,
>     so we can safely say that 'partial ~ using
>     error(WithoutStackTrace)'  in the context of this RFC.
>
>
>     Le 09/06/2021 à 09:31, Julian Ospald a écrit :
>>     Yeah, I think a typeclass to express partiality is a sloppy
>>     technique. I'm not even sure everyone agrees on what 'partial'
>>     means: if my function throws an IO error on relative FilePaths,
>>     is it partial? Is all IO partial?
>>
>>     Haskell is definitely not a total language and I doubt it will
>>     be. I also don't think that it's an interesting goal. It requires
>>     a considerable shift in language design.
>>
>>     HasCallstack sounds like a pragmatic solution, but you could as
>>     well create an alternative prelude that adds it everywhere you
>>     want and then avoid implicit prelude. That won't help you with
>>     unsound dependencies, that don't use it, but it's opt-in, which
>>     seems more reasonable given that it's obviously a somewhat
>>     controversial change.
>>
>>     I'd expect the nay-sayers here, however, to be a driving force in
>>     a better GHC based solution. Otherwise, the next time this comes
>>     up people will say "you had time enough".
>>
>>     On June 8, 2021 6:10:52 PM UTC, Oliver Charles
>>     <ollie at ocharles.org.uk> wrote:
>>
>>
>>
>>         On Tue, 8 Jun 2021, at 6:36 PM, Richard Eisenberg wrote:
>>>         I've been very much of two minds in this debate: On the one
>>>         hand, having these constraints is very practically useful.
>>>         On the other, what we're doing here is very un-Haskellish,
>>>         in that we're letting operational concerns leak into a
>>>         declarative property (a function's type). The reason we're
>>>         doing this is another un-Haskellish thing -- partiality --
>>>         but that ship has sailed.
>>>
>>>         So, may I propose a slightly different way forward?
>>>
>>>         Instead of adding a HasCallStack constraint on these
>>>         functions, add an IsPartial constraint. For example:
>>>
>>>         > head :: IsPartial => [a] -> a
>>>
>>>         This is slightly awkward, still, because IsPartial is a
>>>         class-constraint-like-thing, but it has no parameter. But it
>>>         has a few very nice properties:
>>>         * IsPartial is declarative: it describes a property of the
>>>         function without worrying about its operation.
>>>         * If we think about the way constraints propagate, IsPartial
>>>         has the right semantics: the caller of a partial function
>>>         would itself become partial.
>>
>>         I don't think this is true.
>>
>>         Take:
>>
>>         foo :: Int -> Bool
>>         foo _ = head [True]
>>
>>         Clearly foo is total - it is defined for all of its inputs.
>>         That it uses a partial function in its body isn't observable.
>>         So it's a shame that IsPartial leaks out.
>>
>>         I guess here you'd have me say
>>
>>         foo _ = partialityIsOk $ head [True]
>>
>>         ?
>>
>>         Ollie
>>
>>
>>     _______________________________________________
>>     Libraries mailing list
>>     Libraries at haskell.org
>>     http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries
>
>     -- 
>     Hécate ✨
>     🐦: @TechnoEmpress
>     IRC: Hecate
>     WWW:https://glitchbra.in
>     RUN: BSD
>
-- 
Hécate ✨
🐦: @TechnoEmpress
IRC: Hecate
WWW: https://glitchbra.in
RUN: BSD

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/libraries/attachments/20210609/fd621e5a/attachment-0001.html>


More information about the Libraries mailing list