[Haskell-cafe] incomplete-uni-patterns

Olaf Klinke olf at aatal-apotheke.de
Thu Jan 26 20:58:26 UTC 2023


> From: Tom Ellis <tom-lists-haskell-cafe-2017 at jaguarpaw.co.uk>
> To: haskell-cafe at haskell.org
> Subject: Re: [Haskell-cafe] incomplete-uni-patterns
> 
> On Thu, Jan 26, 2023 at 12:21:31PM +0900, Kazu Yamamoto (山本和彦) via
> Haskell-Cafe wrote:
> > >  I feel I should raise the naive question, what if args is wrong?
> > 
> > The length of "args" have been checked in advance.
> > I'm sure that the length is 2.
> 
> Then, at the point you check the args, put them in a pair?

That seems indeed the most realistic use case, and a semi-automatic
translation by a linter would be cool:

```
if length args >= 2
    then let (addr:port:_) = args in ...
    else complain_about_insufficient_args
```

transforms to

```
case args of
    (addr:port:_) -> ...
    _ -> complain_about_insufficient_args
```

Rice's theorem will get in the way though, since no linter may be able
to prove in general that the first branch in the if-expression can only
be entered if the pattern match within must succeed. The example might
still be tractable, but what about more complicated data
structures/pattern matches? 
I agree with Henning, in this case the incomplete-uni-patterns
rightfully informs you that you should re-structure your code and help
the compiler know what you as the programmer know. 

That said, I've been using the former style and it's okay to have
different opinions about whether it is good style. Personally, I don't
care whether the application aborts on start-up with an incomplete
pattern error or my own complain_about_insufficient_args failure. It
just can't go on. Henning disagrees. Deep within a library, where you
can't control the calling context, such a partial pattern match should
be avoided, of course. 
I collected all my dubious handling of unwanted situations in a module
that is sprinkled with DEPRECATED pragmas reminding me that there is
code to be tidied. For example, 

failLeft :: MonadFail m => Either String a -> m a
failLeft = either fail return 
{-# DEPRECATED failLeft "this can fail, consider proper error handling" #-}

If you are sure that failing is okay at the particular use site, just
replace failLeft by an equivalent version without the DEPRECATED
pragma. That would be the akin to the proposed {-# PARTIAL_MATCH #-}
pragma, but requires you to avoid the incomplete pattern match in the
first place and handle the other patterns somehow. 

Olaf 



More information about the Haskell-Cafe mailing list