rikvdkleij / intellij-haskell

IntelliJ plugin for Haskell
https://rikvdkleij.github.io/intellij-haskell/
Apache License 2.0
1.31k stars 96 forks source link

Case splitting inside where block doesn't work properly #611

Open L7R7 opened 3 years ago

L7R7 commented 3 years ago
data FooType = Foo | Bar Int
newtype Base = Base String

foo :: FooType -> Base -> String
foo a b = undefined
  where
    bar :: FooType -> Base -> String
    bar _ _ = undefined

When case splitting on the implementation line of bar, I end up with:

data FooType = Foo | Bar Int
newtype Base = Base String

foo :: FooType -> Base -> String
foo a b = undefined
  where
    bar :: FooType -> Base -> String
    bar (Bar n) _ = undefined
foo a b = undefined
  where
    bar :: FooType -> Base -> String
    bar Foo _ = undefined

So it correctly splits the cases, but it doesn't generate the correct code.

Also, I can't case split when there's no type annotation for bar. Especially in cases like this I often don't use explicit type annotations. It would be great to have case splitting there

rikvdkleij commented 3 years ago

Thanks for reporting!

Currently only case splitting on top-level is supported. So I have to not show the case split action in this case or make it work in this case. Will take a look soon.

rikvdkleij commented 3 years ago

Got this case also working. Will release a new version soon.

L7R7 commented 3 years ago

Seems to be fixed, except that the cursor jumps to a weird position after case splitting. The above example results in

foo :: FooType -> Base -> String
foo a b = undefined
  where
    bar :: FooType -> Base -> String        x
    bar Foo _ = undefined
    bar (Bar n) _ = undefined

where x is the position of the cursor after the case split. Haven't tried more examples, but I guess it's a general problem

rikvdkleij commented 3 years ago

Thanks! You're a great tester 👍

I got a fix which puts the cursor directly after bar :: FooType -> Base -> String Don't get this better in current implementation. Hopefully you can live with that 😄

mbwgh commented 3 years ago

I noticed that you are able to case split on functions now (tested with beta84), given that it is mentioned in a where block.

For instance, if you have 2020-11-03-071313_268x106_scrot then all is good.

But putting the f inside a where block makes case-splitting available. 2020-11-03-071423_390x117_scrot

And then you end up with something like this: 2020-11-03-071525_310x155_scrot

The same thing happens when you change the argument type to Int and it will pattern match on the constructor. It does not happen for ().

rikvdkleij commented 3 years ago

@mbwgh Thanks! Will try to fix this.

mbwgh commented 3 years ago

With Haskell you never know if there is yet another clever way of writing things. But what I would expect is that I would be able to case split on the e in

myFun = putStrLn . f
  where
    f :: Either Int Bool -> String
    f e = undefined

Preferrably something like that should work even if the type signature for f was omitted, but maybe that is a trickier case.

But yeah, the case split on the f itself was a little surprising for me, but that's subjective as always.

rikvdkleij commented 3 years ago

But what I would expect is that I would be able to case split on the e in

Yes, that's right but not supported at the moment.

But yeah, the case split on the f itself was a little surprising for me, but that's subjective as always.

Yep, In that case the option to apply case splitting should not be available.