ghc should be able to deduce correct use of partial functions and not give a warning in such cases

ghc should be able to deduce correct use of partial functions and not give a warning in such cases, e.g. in 9.8.2 if null ys then [] else [(xs,tail ys)]) gets a warning warning: [GHC-63394] [-Wx-partial] but it is clear that this use of tail will never be a problem so IMHO that line of code should not get a warning. Does anybody know if there is a plan or enhancement request to eliminate such warnings? Cheers George

On Tue, 16 Apr 2024, George Colpitts wrote:
ghc should be able to deduce correct use of partial functions and not give a warning in such cases, e.g. in 9.8.2
if null ys then [] else [(xs,tail ys)])
gets a warning
warning: [GHC-63394] [-Wx-partial]
but it is clear that this use of tail will never be a problem so IMHO that line of code should not get a warning.
Does anybody know if there is a plan or enhancement request to eliminate such warnings?
I would just use good old pattern matching: case ys of [] -> [] _:zs -> [(xs,zs)]

This is what I was going to say. The original poster is right, but still, null is a function. It is one level of indirection away from pattern matching.
On Tuesday, April 16, 2024 at 10:46:56 AM EDT, Henning Thielemann
ghc should be able to deduce correct use of partial functions and not give a warning in such cases, e.g. in 9.8.2
if null ys then [] else [(xs,tail ys)])
gets a warning
warning: [GHC-63394] [-Wx-partial]
but it is clear that this use of tail will never be a problem so IMHO that line of code should not get a warning.
Does anybody know if there is a plan or enhancement request to eliminate such warnings?
I would just use good old pattern matching: case ys of [] -> [] _:zs -> [(xs,zs)]_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

Hi Henning, Thanks for the quick response! Yes, that's basically how I fixed it but I really don't want to have to do that since the code is correct. Not a big deal but may be irritating to beginners or large projects that want to eliminate warnings. Do you think an ER would be rejected ? If I remember correctly there is already detection of incomplete pattern matching that is ok and in such cases warnings are omitted. This would be similar to that. Cheers, George On Tue, Apr 16, 2024 at 11:46 AM Henning Thielemann < lemming@henning-thielemann.de> wrote:
On Tue, 16 Apr 2024, George Colpitts wrote:
ghc should be able to deduce correct use of partial functions and not give a warning in such cases, e.g. in 9.8.2
if null ys then [] else [(xs,tail ys)])
gets a warning
warning: [GHC-63394] [-Wx-partial]
but it is clear that this use of tail will never be a problem so IMHO that line of code should not get a warning.
Does anybody know if there is a plan or enhancement request to eliminate such warnings?
I would just use good old pattern matching:
case ys of [] -> [] _:zs -> [(xs,zs)]

Wouldn't you have to be able to inline null and tail to be able to say that
this use of tail is not partial? If null and tail "live" in a different
library, is there much that you can do?
Thanks,
Ivan
On Tue, 16 Apr 2024 at 07:58, George Colpitts
Hi Henning,
Thanks for the quick response! Yes, that's basically how I fixed it but I really don't want to have to do that since the code is correct. Not a big deal but may be irritating to beginners or large projects that want to eliminate warnings. Do you think an ER would be rejected ? If I remember correctly there is already detection of incomplete pattern matching that is ok and in such cases warnings are omitted. This would be similar to that.
Cheers, George
On Tue, Apr 16, 2024 at 11:46 AM Henning Thielemann < lemming@henning-thielemann.de> wrote:
On Tue, 16 Apr 2024, George Colpitts wrote:
ghc should be able to deduce correct use of partial functions and not give a warning in such cases, e.g. in 9.8.2
if null ys then [] else [(xs,tail ys)])
gets a warning
warning: [GHC-63394] [-Wx-partial]
but it is clear that this use of tail will never be a problem so IMHO that line of code should not get a warning.
Does anybody know if there is a plan or enhancement request to eliminate such warnings?
I would just use good old pattern matching:
case ys of [] -> [] _:zs -> [(xs,zs)]
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

On Tue, 16 Apr 2024, George Colpitts wrote:
Yes, that's basically how I fixed it but I really don't want to have to do that since the code is correct. Not a big deal but may be irritating to beginners or large projects that want to eliminate warnings. Do you think an ER would be rejected ? If I remember correctly there is already detection of incomplete pattern matching that is ok and in such cases warnings are omitted. This would be similar to that.
To my human linter 'tail' looks always suspicious and needs an additional mental check, that 'tail' is no problem in your special case. The pattern match does not have this problem. It both improves readability and convinces GHC easily. That's what the warning shall achieve and it is even a good guide to beginners.

Makes sense ! On Tue, Apr 16, 2024 at 12:45 PM Henning Thielemann < lemming@henning-thielemann.de> wrote:
On Tue, 16 Apr 2024, George Colpitts wrote:
Yes, that's basically how I fixed it but I really don't want to have to do that since the code is correct. Not a big deal but may be irritating to beginners or large projects that want to eliminate warnings. Do you think an ER would be rejected ? If I remember correctly there is already detection of incomplete pattern matching that is ok and in such cases warnings are omitted. This would be similar to that.
To my human linter 'tail' looks always suspicious and needs an additional mental check, that 'tail' is no problem in your special case. The pattern match does not have this problem. It both improves readability and convinces GHC easily. That's what the warning shall achieve and it is even a good guide to beginners.

It seems that I can replace
if null ys then [] else [(xs,tail ys)])
with
if null ys then [] else [(xs, Safe.tailErr ys)])
and not get any warnings so I think I am going to do that. I'm surprised
that the warning doesn't mention that option to fix the issue. Do you see
any issues with this fix?
Thanks,
George
On Tue, Apr 16, 2024 at 11:57 AM George Colpitts
Hi Henning,
Thanks for the quick response! Yes, that's basically how I fixed it but I really don't want to have to do that since the code is correct. Not a big deal but may be irritating to beginners or large projects that want to eliminate warnings. Do you think an ER would be rejected ? If I remember correctly there is already detection of incomplete pattern matching that is ok and in such cases warnings are omitted. This would be similar to that.
Cheers, George
On Tue, Apr 16, 2024 at 11:46 AM Henning Thielemann < lemming@henning-thielemann.de> wrote:
On Tue, 16 Apr 2024, George Colpitts wrote:
ghc should be able to deduce correct use of partial functions and not give a warning in such cases, e.g. in 9.8.2
if null ys then [] else [(xs,tail ys)])
gets a warning
warning: [GHC-63394] [-Wx-partial]
but it is clear that this use of tail will never be a problem so IMHO that line of code should not get a warning.
Does anybody know if there is a plan or enhancement request to eliminate such warnings?
I would just use good old pattern matching:
case ys of [] -> [] _:zs -> [(xs,zs)]

Is pattern matching more elegant than Safe.tailErr ? Pattern matching makes your meaning visible to the eye.
On Thursday, April 18, 2024 at 06:24:29 PM EDT, George Colpitts
ghc should be able to deduce correct use of partial functions and not give a warning in such cases, e.g. in 9.8.2
if null ys then [] else [(xs,tail ys)])
gets a warning
warning: [GHC-63394] [-Wx-partial]
but it is clear that this use of tail will never be a problem so IMHO that line of code should not get a warning.
Does anybody know if there is a plan or enhancement request to eliminate such warnings?
I would just use good old pattern matching: case ys of [] -> [] _:zs -> [(xs,zs)] _______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

I do see a problem with the use of Safe.tailErr in this example
and that is that it turns something that could be simple and obvious
into something quite obscure.
On Fri, 19 Apr 2024 at 10:24, George Colpitts
It seems that I can replace
if null ys then [] else [(xs,tail ys)])
with
if null ys then [] else [(xs, Safe.tailErr ys)])
and not get any warnings so I think I am going to do that. I'm surprised that the warning doesn't mention that option to fix the issue. Do you see any issues with this fix?
Thanks, George
On Tue, Apr 16, 2024 at 11:57 AM George Colpitts
wrote: Hi Henning,
Thanks for the quick response! Yes, that's basically how I fixed it but I really don't want to have to do that since the code is correct. Not a big deal but may be irritating to beginners or large projects that want to eliminate warnings. Do you think an ER would be rejected ? If I remember correctly there is already detection of incomplete pattern matching that is ok and in such cases warnings are omitted. This would be similar to that.
Cheers, George
On Tue, Apr 16, 2024 at 11:46 AM Henning Thielemann
wrote: On Tue, 16 Apr 2024, George Colpitts wrote:
ghc should be able to deduce correct use of partial functions and not give a warning in such cases, e.g. in 9.8.2
if null ys then [] else [(xs,tail ys)])
gets a warning
warning: [GHC-63394] [-Wx-partial]
but it is clear that this use of tail will never be a problem so IMHO that line of code should not get a warning.
Does anybody know if there is a plan or enhancement request to eliminate such warnings?
I would just use good old pattern matching:
case ys of [] -> [] _:zs -> [(xs,zs)]
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

I'm not 100% sure what Safe.tailErr function you are using (Hoogle only finds tailErr :: e -> [a] -> Either e [a] https://hackage.haskell.org/package/errors-2.3.0/docs/Control-Error-Safe.htm..., which doesn't appear compatible with the way you're using it since it takes an "error message" as first argument). But regardless, any sort of tail function (whether "safe" or not) is going to have to work by pattern matching on the list again. null is a perfectly ordinary function that pattern matches on a list to decide whether to return True or False, and the if/then/else syntax is also essentially just special-purpose syntax for pattern matching a Bool. So your code is essentially pattern matching on a list to decide whether it's empty or not, throwing away the result of that and keeping a Bool instead, then pattern matching on the Bool to split between two cases, then pattern matching on the list again. If you had kept the result of the first pattern match there would be no need for the latter two. Essentially the problem is "boolean blindness" (if you search online you'll find a number of articles elaborating on the concept). All being inside the else branch inherently tells you is that a Bool was False. It doesn't tell you that the list is non-empty, and so it's safe to apply tail. To know that additional information you (either the human code reader or the compiler) have to keep track of additional facts about where the Bool came from (and already know or be able to look inside the definitions of null and tail). In this trivial example this is easy work for a human, and in principle feasible for the compiler to keep track of, but it's still work. So False just isn't a very good way to encode the information "a list is non-empty". If you instead use pattern matching, you get: case ys of [] -> [] (y:ysTail) -> [(xs, ysTail)] Here the evidence you get out of your check when the list is non-empty isn't just a featureless False, you get evidence that the list is non-empty (and therefore has a head and a tail) by actually getting access to the head and tail. Neither you nor the compiler has to remember that False means the list isn't empty and so it's safe to extract the tail; you just have the tail! This style of coding is generally more readable, maintainable, and less error-prone. So much so that I would opine that the compiler maintainers should specifically avoid making the compiler keep track of the provenance of Bools used in if conditions so it can suppress partiality warnings. Needing to suppress partiality warnings is usually itself a warning sign; often (not always, but often) it's an indicator that you're using simple checks where using richer evidence would work better. If you're a Haskell programmer, you should be comfortable with pattern matching as the primary tool for switching between code branches, rather than test and if, so warnings that nudge beginners away from if null as a pattern are a good thing. (In principle the if+null+tail pattern you're using is less efficient, too. It makes 2 function calls and 3 pattern matches, where a single pattern match would suffice. I mention this later as I think the logic issues of the code are more important, and it's unlikely to be a major issue in practice; the compiler will probably inline and optimise away the extra function calls and pattern matches anyway. But it is another reason to prefer carrying the information you need from the place you checked it, rather than looking into a structure to check that what you need is present and then later looking into the structure again to actually extract what you need. In more complex cases it could be a genuine efficiency concern.) Cheers, Ben 18 Apr 2024, 10:24 pm by george.colpitts@gmail.com:
It seems that I can replace
if null ys then [] else [(xs,tail ys)])
with
if null ys then [] else [(xs, Safe.tailErr ys)])
and not get any warnings so I think I am going to do that. I'm surprised that the warning doesn't mention that option to fix the issue. Do you see any issues with this fix?
Thanks, George
On Tue, Apr 16, 2024 at 11:57 AM George Colpitts <> george.colpitts@gmail.com> > wrote:
Hi Henning,
Thanks for the quick response! Yes, that's basically how I fixed it but I really don't want to have to do that since the code is correct. Not a big deal but may be irritating to beginners or large projects that want to eliminate warnings. Do you think an ER would be rejected ? If I remember correctly there is already detection of incomplete pattern matching that is ok and in such cases warnings are omitted. This would be similar to that.
Cheers, George
On Tue, Apr 16, 2024 at 11:46 AM Henning Thielemann <>> lemming@henning-thielemann.de>> > wrote:
On Tue, 16 Apr 2024, George Colpitts wrote:
ghc should be able to deduce correct use of partial functions and not give a warning in such cases, e.g. in 9.8.2
if null ys then [] else [(xs,tail ys)])
gets a warning
warning: [GHC-63394] [-Wx-partial]
but it is clear that this use of tail will never be a problem so IMHO that line of code should not get a warning.
Does anybody know if there is a plan or enhancement request to eliminate such warnings?
I would just use good old pattern matching:
case ys of [] -> [] _:zs -> [(xs,zs)]

On Fri, 19 Apr 2024, Ben via Haskell-Cafe wrote:
I'm not 100% sure what Safe.tailErr function you are using (Hoogle only finds tailErr :: e -> [a] -> Either e [a], which doesn't appear compatible with the way you're using it since it takes an "error message" as first argument).
I found this one: https://hackage.haskell.org/package/safe-0.3.21/docs/Safe.html#v:tailErr It is problematic in even more ways. First, the reader of the code does not know, which tailErr the programmer means. We must look it up. Even if there would be only one candidate, we must look up what it does. Second, the documentation says, tailErr is meant to suppress the new warning on 'tail' in GHC>=9.8, but is still partial. Not a good idea to suppress a warning that has a purpose. Third, the naming of the 'safe' package and 'Safe' module is misleading, because there is nothing unsafe in 'tail'&Co. in the sense of SafeHaskell or unsafePerformIO. 'tail' is partial, that is, for some inputs it is undefined, read: it may run into an infinite loop. But it will not cause memory corruption or ignite nukes while pretending to stay away from IO.

Thanks for everybody's replies
To give more context the original code from Ch. 12 of Bird's *Thinking
Functionally with Haskell* was:
let (xs, ys) = break (== ch) str in
if null ys then [] else [(xs, tail ys)])
I replaced it with
let (xs, ys@(_ : t)) = break (== ch) str in
if null ys then [] else [(xs, t)])
On Tue, Apr 16, 2024 at 10:51 AM George Colpitts
ghc should be able to deduce correct use of partial functions and not give a warning in such cases, e.g. in 9.8.2
if null ys then [] else [(xs,tail ys)])
gets a warning
warning: [GHC-63394] [-Wx-partial]
but it is clear that this use of tail will never be a problem so IMHO that line of code should not get a warning.
Does anybody know if there is a plan or enhancement request to eliminate such warnings?
Cheers George

On Sat, 20 Apr 2024, George Colpitts wrote:
Thanks for everybody's replies
To give more context the original code from Ch. 12 of Bird's Thinking Functionally with Haskell was:
let (xs, ys) = break (== ch) str in
if null ys then [] else [(xs, tail ys)])
I replaced it with
let (xs, ys@(_ : t)) = break (== ch) str in
if null ys then [] else [(xs, t)])
This won't work. ys@(_ : t) only matches on non-empty lists. It will also give you warnings, but this warning may not be contained in -Wall depending on the GHC version.

Hi George, If you do not want to pattern match on `ys`, the simplest solution is to do what the GHC warning suggests you to do and use `drop 1` instead of `tail`. Another alternative is `Data.List.uncons` followed by `Data.Maybe.maybe`. Best regards, Andrew
On 20 Apr 2024, at 13:28, George Colpitts
wrote: Thanks for everybody's replies
To give more context the original code from Ch. 12 of Bird's Thinking Functionally with Haskell was:
let (xs, ys) = break (== ch) str in if null ys then [] else [(xs, tail ys)])
I replaced it with
let (xs, ys@(_ : t)) = break (== ch) str in if null ys then [] else [(xs, t)])
On Tue, Apr 16, 2024 at 10:51 AM George Colpitts
mailto:george.colpitts@gmail.com> wrote: ghc should be able to deduce correct use of partial functions and not give a warning in such cases, e.g. in 9.8.2
if null ys then [] else [(xs,tail ys)])
gets a warning
warning: [GHC-63394] [-Wx-partial]
but it is clear that this use of tail will never be a problem so IMHO that line of code should not get a warning.
Does anybody know if there is a plan or enhancement request to eliminate such warnings?
Cheers George
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

I've decided to stick with case and pattern matching as Henning suggested in his original reply. Thanks On Sat, Apr 20, 2024 at 12:30 PM Andrew Lelechenko < andrew.lelechenko@gmail.com> wrote:
Hi George,
If you do not want to pattern match on `ys`, the simplest solution is to do what the GHC warning suggests you to do and use `drop 1` instead of `tail`. Another alternative is `Data.List.uncons` followed by `Data.Maybe.maybe`.
Best regards, Andrew
On 20 Apr 2024, at 13:28, George Colpitts
wrote: Thanks for everybody's replies
To give more context the original code from Ch. 12 of Bird's *Thinking Functionally with Haskell* was:
let (xs, ys) = break (== ch) str in
if null ys then [] else [(xs, tail ys)])
I replaced it with
let (xs, ys@(_ : t)) = break (== ch) str in
if null ys then [] else [(xs, t)])
On Tue, Apr 16, 2024 at 10:51 AM George Colpitts < george.colpitts@gmail.com> wrote:
ghc should be able to deduce correct use of partial functions and not give a warning in such cases, e.g. in 9.8.2
if null ys then [] else [(xs,tail ys)])
gets a warning
warning: [GHC-63394] [-Wx-partial]
but it is clear that this use of tail will never be a problem so IMHO that line of code should not get a warning.
Does anybody know if there is a plan or enhancement request to eliminate such warnings?
Cheers George
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

The clearest way that I know to write that code fragment is
case break (== ch) str of
(_,[]) -> []
(xs,(_:ys)) -> [(xs,ys)]
It's one line longer, but there are no warnings and NO SURPRISES for the reader.
The version that matches on (_:_) before testing whether that's
possible surprised
me mightly. Confused me, even.
On Sun, 21 Apr 2024 at 00:29, George Colpitts
Thanks for everybody's replies
To give more context the original code from Ch. 12 of Bird's Thinking Functionally with Haskell was:
let (xs, ys) = break (== ch) str in
if null ys then [] else [(xs, tail ys)])
I replaced it with
let (xs, ys@(_ : t)) = break (== ch) str in
if null ys then [] else [(xs, t)])
On Tue, Apr 16, 2024 at 10:51 AM George Colpitts
wrote: ghc should be able to deduce correct use of partial functions and not give a warning in such cases, e.g. in 9.8.2
if null ys then [] else [(xs,tail ys)])
gets a warning
warning: [GHC-63394] [-Wx-partial]
but it is clear that this use of tail will never be a problem so IMHO that line of code should not get a warning.
Does anybody know if there is a plan or enhancement request to eliminate such warnings?
Cheers George
_______________________________________________ Haskell-Cafe mailing list To (un)subscribe, modify options or view archives go to: http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe Only members subscribed via the mailman list are allowed to post.

On Sun, Apr 21, 2024 at 01:17:26PM +1200, Richard O'Keefe wrote:
The clearest way that I know to write that code fragment is case break (== ch) str of (_,[]) -> [] (xs,(_:ys)) -> [(xs,ys)]
I'd also consider changing the return type from `[([a], [a])]` to `Maybe ([a], [a])`, as in: maybeSplit :: Eq a => a -> [a] -> Maybe ([a], [a]) maybeSplit sep xs = case break (== sep) xs of (ys, (_:zs)) -> Just (ys, zs) _ -> Nothing A list of at most one element begs to be a `Maybe` instead. -- Viktor.
participants (8)
-
Andrew Lelechenko
-
Ben
-
George Colpitts
-
Henning Thielemann
-
Ivan Perez
-
Mark McConnell
-
Richard O'Keefe
-
Viktor Dukhovni