rikvdkleij / intellij-haskell

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

Question about a use case: folding over a data structure #629

Closed mbwgh closed 3 years ago

mbwgh commented 3 years ago

There are probably more suitable titles I could have chosen, but at this point I am not sure if my issue is trivial, or if it touches on a multitude of subjects.

Suppose you have some fancy data structure you want to apply a higher order function on, and the types get complicated. I want my code to look something like this:

fun :: A.ComplicatedType -> Int
fun = A.foldl' go 0
  where
    go :: ?
    go = ?

Since it has been a while, I have no idea what the arguments to A.foldl' were, and in what order they should go. The compiler could in theory infer this. But if you write something like this:

fun = A.foldl' go 0
  where
    go = _
    go = undefined

The inferred type in the where block is too generall, while in

fun = A.foldl' _ 0

the right type constraints would be inferred for the error message belonging to the typed hole.

Is there some convenient way have Intellij fill in the blanks the way I want? I.e. what is the fastest way to get to something like

fun :: A.ComplicatedType -> Int
fun = A.foldl' go 0
  where
    go :: Int -> A.Element -> Int
    go n x = undefined

or some other suitable template, so I don't have to spend time trying to piece types together in my head (or using ghci, or by abusing GHC errors etc.)?

Of course, the pattern I used is not a must, if there's a simple and ergonomic workaround, I'll take it :)

rikvdkleij commented 3 years ago

Thanks for reporting!

Is there some convenient way have Intellij fill in the blanks the way I want?

A current feature which comes closest is smart completion which is using the info of typed holes.

Of course, the pattern I used is not a must, if there's a simple and ergonomic workaround, I'll take it :)

Will do some investigation 😄

mbwgh commented 3 years ago

Maybe it would be desirable (and possible and feasible) to have a "create stub" intention where a function skeleton can be created from a compiler error referring to either a missing function or a typed hole?

I.e., to borrow from the above example again, if you have

fun :: A.ComplicatedType -> Int
fun = A.foldl' go 0

or

fun :: A.ComplicatedType -> Int
fun = A.foldl' _ 0

you could hover over go or the _ and create a stub using alt+Enter?

mbwgh commented 3 years ago

Closing since this is now addressed at least to some extent.