out-commented code vs. case with redundant pattern matches

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

out-commented code vs. case with redundant pattern matches

Henning Thielemann

Occasionally I have multiple implementations of the same task and want to
choose one quickly but statically. I do not want to out-comment unused
branches because they shall still be type checked. So far I used this
scheme:

    case 0::Int of
       0 -> putStrLn "A"
       1 -> putStrLn "B"
       _ -> putStrLn "C"

With ghc-8.0.2 and ghc-8.2.2 I get these warnings:

RedundantCase.hs:4:7: warning: [-Woverlapping-patterns]
     Pattern match is redundant
     In a case alternative: 0 -> ...

RedundantCase.hs:5:7: warning: [-Woverlapping-patterns]
     Pattern match is redundant
     In a case alternative: 1 -> ...

I thought that "redundant" means that the first two cases overlap with
'_'. But if I replace '_' by '2' I get not only the non-exhaustive
patterns warning but an additional redundancy warning on pattern '2'.

Is there a nice way to tell GHC that the unused branches are intended,
without generally disabling overlapping patterns warning?

I mean, this one does not provoke any warnings:

    if True
      then putStrLn "X"
      else putStrLn "Y"

but is limited to two branches.
_______________________________________________
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.
Reply | Threaded
Open this post in threaded view
|

Re: out-commented code vs. case with redundant pattern matches

Sergiu Ivanov-2
Hi Henning,

Thus quoth  Henning Thielemann  on Wed Nov 29 2017 at 11:04 (+0100):
> Occasionally I have multiple implementations of the same task and want to
> choose one quickly but statically. I do not want to out-comment unused
> branches because they shall still be type checked. So far I used this
> scheme:
>
>     case 0::Int of
>        0 -> putStrLn "A"
>        1 -> putStrLn "B"
>        _ -> putStrLn "C"

Maybe you can factor out the implementations of different branches into
separate functions, like in:

  case 0 :: Int of
    0 -> putStrLn "A"
    1 -> handleOne1
  where
    handleOne1 :: Int -> IO ()
    handleOne1 = putStrLn "B"

    handleOne1 :: Int -> IO ()
    handleOne2 = putStrLn "C"

This should keep the typechecking.

> With ghc-8.0.2 and ghc-8.2.2 I get these warnings:
>
> RedundantCase.hs:4:7: warning: [-Woverlapping-patterns]
>      Pattern match is redundant
>      In a case alternative: 0 -> ...
>
> RedundantCase.hs:5:7: warning: [-Woverlapping-patterns]
>      Pattern match is redundant
>      In a case alternative: 1 -> ...
>
> I thought that "redundant" means that the first two cases overlap with
> '_'. But if I replace '_' by '2' I get not only the non-exhaustive
> patterns warning but an additional redundancy warning on pattern '2'.
>
> Is there a nice way to tell GHC that the unused branches are intended,
> without generally disabling overlapping patterns warning?
To me, you are creating overlapping patterns in the case statements, so
having unused branches and _not_ having warnings about them kind of
breaks the point of this type of warning (personal opinion).

Now, depending on the localisation of alternative branches, you may want
to use per-file preprocessor directives to disable the warning.

--
Sergiu


> I mean, this one does not provoke any warnings:
>
>     if True
>       then putStrLn "X"
>       else putStrLn "Y"
>
> but is limited to two branches.
> _______________________________________________
> 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.

_______________________________________________
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.

signature.asc (497 bytes) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: out-commented code vs. case with redundant pattern matches

Henning Thielemann

On Wed, 29 Nov 2017, Sergiu Ivanov wrote:

> Hi Henning,
>
> Maybe you can factor out the implementations of different branches into
> separate functions, like in:
>
>  case 0 :: Int of
>    0 -> putStrLn "A"
>    1 -> handleOne1
>  where
>    handleOne1 :: Int -> IO ()
>    handleOne1 = putStrLn "B"
>
>    handleOne1 :: Int -> IO ()
>    handleOne2 = putStrLn "C"

I had something similar in mind and found it too complicated. I could also
omit 'case' completely, and directly call handleOne1 and prefix unused
handleOne's with an underscore. Maybe it is the best I can do for now.

> To me, you are creating overlapping patterns in the case statements, so
> having unused branches and _not_ having warnings about them kind of
> breaks the point of this type of warning (personal opinion).

Not quite. We can silence "unused" warnings for variables by prepending an
underscore. Something similar might work for case patterns.
_______________________________________________
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.
Reply | Threaded
Open this post in threaded view
|

Re: out-commented code vs. case with redundant pattern matches

Sylvain Henry-2
In reply to this post by Henning Thielemann
 > I thought that "redundant" means that the first two cases overlap
with '_'. But if I replace '_' by '2' I get not only the non-exhaustive
patterns warning but an additional redundancy warning on pattern '2'.

I think it's a bug of the PM check instead: it doesn't correctly detect
redundant Int alternatives ("1" and "_" in your example). Could you
report it as a bug?
Note that it works as expected with Integer: "case 0 :: Integer of"
reports "1 ->..." and "_ -> ..." as redundant.


A solution to avoid the warning is:

    let choosePut = 0 :: Int

    case choosePut of
       0 -> putStrLn "A"
       1 -> putStrLn "B"
       _ -> putStrLn "C"


-Sylvain


On 29/11/2017 11:04, Henning Thielemann wrote:

>
> Occasionally I have multiple implementations of the same task and want
> to choose one quickly but statically. I do not want to out-comment
> unused branches because they shall still be type checked. So far I
> used this scheme:
>
>    case 0::Int of
>       0 -> putStrLn "A"
>       1 -> putStrLn "B"
>       _ -> putStrLn "C"
>
> With ghc-8.0.2 and ghc-8.2.2 I get these warnings:
>
> RedundantCase.hs:4:7: warning: [-Woverlapping-patterns]
>     Pattern match is redundant
>     In a case alternative: 0 -> ...
>
> RedundantCase.hs:5:7: warning: [-Woverlapping-patterns]
>     Pattern match is redundant
>     In a case alternative: 1 -> ...
>
> I thought that "redundant" means that the first two cases overlap with
> '_'. But if I replace '_' by '2' I get not only the non-exhaustive
> patterns warning but an additional redundancy warning on pattern '2'.
>
> Is there a nice way to tell GHC that the unused branches are intended,
> without generally disabling overlapping patterns warning?
>
> I mean, this one does not provoke any warnings:
>
>    if True
>      then putStrLn "X"
>      else putStrLn "Y"
>
> but is limited to two branches.
> _______________________________________________
> 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.

_______________________________________________
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.
Reply | Threaded
Open this post in threaded view
|

Re: out-commented code vs. case with redundant pattern matches

Doug McIlroy
In reply to this post by Henning Thielemann

Surely GHC is too clever by half in asserting that just 1 of two
impossible branches is redundant in the code

>     case 0::Int of
>        0 -> putStrLn "A"
>        1 -> putStrLn "B"
>        _ -> putStrLn "C"

The assertion suggests that GHC code optimization would leave
some useless vestige of the third case,

The long-range solution to Thielmann's quandry is a bug report.

Doug
_______________________________________________
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.
Reply | Threaded
Open this post in threaded view
|

Re: out-commented code vs. case with redundant pattern matches

Olaf Klinke
In reply to this post by Henning Thielemann
Henning,

how about putting the branches into their own variables. Admittedly this pollutes the namespace but is much more readable IMHO.

workflow = new_workflow where
  new_workflow = putStrLn "A"
  old_workflow = putStrLn "B"

I suppose GHC complains neither about unused where clauses nor about unused top-level bindings. At least with GHCi 7.8.3 the above code produces no warnings.

Olaf
_______________________________________________
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.
Reply | Threaded
Open this post in threaded view
|

Re: out-commented code vs. case with redundant pattern matches

Henning Thielemann

On Wed, 29 Nov 2017, Olaf Klinke wrote:

> Henning,
>
> how about putting the branches into their own variables. Admittedly this pollutes the namespace but is much more readable IMHO.
>
> workflow = new_workflow where
>  new_workflow = putStrLn "A"
>  old_workflow = putStrLn "B"
>
> I suppose GHC complains neither about unused where clauses nor about
> unused top-level bindings. At least with GHCi 7.8.3 the above code
> produces no warnings.

It complains with -Wall, which is a good thing. But in this case I can
suppress the warning individually by prepending an underscore.
_______________________________________________
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.
Reply | Threaded
Open this post in threaded view
|

Re: out-commented code vs. case with redundant pattern matches

Henning Thielemann
In reply to this post by Sergiu Ivanov-2

On Wed, 29 Nov 2017, Sergiu Ivanov wrote:

> Thus quoth  Henning Thielemann  on Wed Nov 29 2017 at 11:04 (+0100):
>> Occasionally I have multiple implementations of the same task and want to
>> choose one quickly but statically. I do not want to out-comment unused
>> branches because they shall still be type checked. So far I used this
>> scheme:
>>
>>     case 0::Int of
>>        0 -> putStrLn "A"
>>        1 -> putStrLn "B"
>>        _ -> putStrLn "C"

I have filed a GHC ticket:
    https://ghc.haskell.org/trac/ghc/ticket/14546
_______________________________________________
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.
Reply | Threaded
Open this post in threaded view
|

Re: out-commented code vs. case with redundant pattern matches

Joachim Breitner-2
In reply to this post by Henning Thielemann
Hi,

Am Mittwoch, den 29.11.2017, 11:04 +0100 schrieb Henning Thielemann:
> Occasionally I have multiple implementations of the same task and want to
> choose one quickly but statically. I do not want to out-comment unused
> branches because they shall still be type checked. So far I used this
> scheme:
>
>     case 0::Int of
>        0 -> putStrLn "A"
>        1 -> putStrLn "B"
>        _ -> putStrLn "C"

You can write

case id (0::Int) of
  0 -> putStrLn "A"
  1 -> putStrLn "B"
  _ -> putStrLn "C"


instead.


> I mean, this one does not provoke any warnings:
>
>     if True
>       then putStrLn "X"
>       else putStrLn "Y"
>
> but is limited to two branches.

It looks like a but that it warns for Int, but not for Bool… freel free
to report that (https://ghc.haskell.org/trac/ghc/wiki/ReportABug).

Joachim

--
Joachim “nomeata” Breitner
  [hidden email]
  https://www.joachim-breitner.de/

_______________________________________________
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.

signature.asc (849 bytes) Download Attachment