<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body>
<div dir="auto">I'm not 100% sure what <span style="font-family: monospace, sans-serif;" class="">Safe.tailErr</span> function you are using (Hoogle only finds <span style="font-family: monospace, sans-serif;" class=""><a href="https://hackage.haskell.org/package/errors-2.3.0/docs/Control-Error-Safe.html#v:tailErr" rel="noopener noreferrer" target="_blank">tailErr :: e -> [a] -> Either e [a]</a></span>, which doesn't appear compatible with the way you're using it since it takes an "error message" as first argument).<br></div><div dir="auto"><br></div><div dir="auto">But regardless, any sort of <span style="font-family: monospace, sans-serif;" class="">tail</span> function (whether "safe" or not) is going to have to work by pattern matching on the list again. <span style="font-family: monospace, sans-serif;" class="">null</span> is a perfectly ordinary function that pattern matches on a list to decide whether to return <span style="font-family: monospace, sans-serif;" class="">True</span> or <span style="font-family: monospace, sans-serif;" class="">False</span>, and the <span style="font-family: monospace, sans-serif;" class="">if/then/else</span> syntax is also essentially just special-purpose syntax for pattern matching a <span style="font-family: monospace, sans-serif;" class="">Bool</span>. 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 <span style="font-family: monospace, sans-serif;" class="">Bool</span> instead, then pattern matching on the <span style="font-family: monospace, sans-serif;" class="">Bool</span> to split between two cases, then pattern matching on the list <i>again</i>. If you had kept the result of the first pattern match there would be no need for the latter two.<br></div><div dir="auto"><br></div><div dir="auto">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 <span style="font-family: monospace, sans-serif;" class="">else</span> branch inherently tells you is that a <span style="font-family: monospace, sans-serif;" class="">Bool</span> was <span style="font-family: monospace, sans-serif;" class="">False</span>. It doesn't tell you that the list is non-empty, and so it's safe to apply <span style="font-family: monospace, sans-serif;" class="">tail</span>. 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 <span style="font-family: monospace, sans-serif;" class="">null</span> and <span style="font-family: monospace, sans-serif;" class="">tail</span>). 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 <span style="font-family: monospace, sans-serif;" class="">False</span> just isn't a very good way to encode the information "a list is non-empty".<br></div><div dir="auto"><br></div><div dir="auto">If you instead use pattern matching, you get:<br></div><div dir="auto"><br></div><div dir="auto"><span style="font-family: monospace, sans-serif;" class="">case ys of</span><br></div><div dir="auto"><span style="font-family: monospace, sans-serif;" class=""> [] -> []</span><br></div><div dir="auto"><span style="font-family: monospace, sans-serif;" class=""> (y:ysTail) -> [(xs, ysTail)]</span><br></div><div dir="auto"><br></div><div dir="auto">Here the evidence you get out of your check when the list is non-empty isn't just a featureless <span style="font-family: monospace, sans-serif;" class="">False</span>, you get evidence that the list is non-empty (and therefore has a head and a tail) by <i>actually getting access to</i> the head and tail. Neither you nor the compiler has to remember that <span style="font-family: monospace, sans-serif;" class="">False</span> means the list isn't empty and so it's safe to extract the tail; you just have the tail!<br></div><div dir="auto"><br></div><div dir="auto">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 <b>avoid</b> making the compiler keep track of the provenance of <span style="font-family: monospace, sans-serif;" class="">Bool</span>s used in <span style="font-family: monospace, sans-serif;" class="">if</span> conditions so it can suppress partiality warnings. <i>Needing</i> 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 <i>should</i> be comfortable with pattern matching as the primary tool for switching between code branches, rather than test and <span style="font-family: monospace, sans-serif;" class="">if</span>, so warnings that nudge beginners away from <span style="font-family: monospace, sans-serif;" class="">if null</span> as a pattern are a good thing.<br></div><div dir="auto"><br></div><div dir="auto">(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 <i>could</i> be a genuine efficiency concern.)<br></div><div dir="auto"><br></div><div dir="auto">Cheers,<br></div><div dir="auto">Ben<br></div><div dir="auto"><br></div><div dir="auto"><br></div><div dir="auto">18 Apr 2024, 10:24 pm by george.colpitts@gmail.com:<br></div><blockquote class="tutanota_quote" style="border-left: 1px solid #93A3B8; padding-left: 10px; margin-left: 5px;"><div dir="ltr"><div dir="ltr"><div class="" style="font-family:"times new roman",serif;font-size:large">It seems that I can replace <br></div><div class="" style="font-family:"times new roman",serif;font-size:large"><br></div></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div dir="ltr"><div class="" style="font-family:"times new roman",serif;font-size:large"><span style="font-family:Arial, Helvetica, sans-serif" class=""><span style="font-size:small" class=""> if null ys then [] else [(xs,tail ys)])</span></span><br></div><div class="" style="font-family:"times new roman",serif;font-size:large"><span style="font-family:Arial, Helvetica, sans-serif" class=""><span style="font-size:small" class=""></span></span><br></div></div></blockquote><div class="" style="font-family:"times new roman",serif;font-size:large">with <br></div><div class="" style="font-family:"times new roman",serif;font-size:large"><br></div><blockquote style="margin:0 0 0 40px;border:none;padding:0px"><div class="" style="font-family:"times new roman",serif;font-size:large">if null ys then [] else [(xs, Safe.tailErr ys)])<br></div></blockquote><div dir="auto"><br></div><div dir="ltr"><div class="" style="font-family:"times new roman",serif;font-size:large">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?<br></div><div class="" style="font-family:"times new roman",serif;font-size:large"><br></div><div class="" style="font-family:"times new roman",serif;font-size:large">Thanks,<br></div><div class="" style="font-family:"times new roman",serif;font-size:large">George<br></div><div class="" style="font-family:"times new roman",serif;font-size:large"><br></div></div><div dir="auto"><br></div><div class=""><div dir="ltr" class="">On Tue, Apr 16, 2024 at 11:57 AM George Colpitts <<a target="_blank" rel="noopener noreferrer" href="mailto:george.colpitts@gmail.com">george.colpitts@gmail.com</a>> wrote:<br></div><blockquote class="" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div style="font-family:"times new roman",serif;font-size:large">Hi Henning,<br></div><div style="font-family:"times new roman",serif;font-size:large"><br></div><div style="font-family:"times new roman",serif;font-size:large">Thanks for the quick response!<br></div><div style="font-family:"times new roman",serif;font-size:large">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.<br></div><div style="font-family:"times new roman",serif;font-size:large"><br></div><div style="font-family:"times new roman",serif;font-size:large">Cheers,<br></div><div style="font-family:"times new roman",serif;font-size:large">George<br></div><div style="font-family:"times new roman",serif;font-size:large"><br></div></div><div dir="auto"><br></div><div class=""><div dir="ltr" class="">On Tue, Apr 16, 2024 at 11:46 AM Henning Thielemann <<a rel="noopener noreferrer" href="mailto:lemming@henning-thielemann.de" target="_blank">lemming@henning-thielemann.de</a>> wrote:<br></div><blockquote class="" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="auto"><br></div><div dir="auto">On Tue, 16 Apr 2024, George Colpitts wrote:<br></div><div dir="auto"> <br></div><div dir="auto"> > ghc should be able to deduce correct use of partial functions and not give a warning in such cases, e.g.<br></div><div dir="auto"> > in 9.8.2<br></div><div dir="auto"> > <br></div><div dir="auto"> > if null ys then [] else [(xs,tail ys)])<br></div><div dir="auto"> > <br></div><div dir="auto"> > gets a warning<br></div><div dir="auto"> > <br></div><div dir="auto"> > warning: [GHC-63394] [-Wx-partial]<br></div><div dir="auto"> > <br></div><div dir="auto"> > but it is clear that this use of tail will never be a problem so IMHO that line of code should not get a<br></div><div dir="auto"> > warning. <br></div><div dir="auto"> > <br></div><div dir="auto"> > Does anybody know if there is a plan or enhancement request to eliminate such warnings? <br></div><div dir="auto"> <br></div><div dir="auto"> <br></div><div dir="auto"> I would just use good old pattern matching:<br></div><div dir="auto"> <br></div><div dir="auto"> case ys of<br></div><div dir="auto"> [] -> []<br></div><div dir="auto"> _:zs -> [(xs,zs)]<br></div></blockquote></div></blockquote></div></div></blockquote><div dir="auto"><br></div> </body>
</html>