Flexible Haskell - a new plugin for JetBrains IDEs

Hey everybody,

glad to be in touch. I recently launched a Haskell language implemntation for all JetBrains IDEs (IntelliJ, PyCharm, CLion, GoLand, RubyMine etc) and am now looking for early adopters.

It is called “Flexible Haskell” and is a ground-up new language implementation with a full Haskell grammar (BNF/JFlex). You can find it on the Marketplace (searching “Flexible Haskell” should do the trick).


Here’s a quick screenshots:

Even though it’s a new plugin, I tried to push out a solid set of features from the start: HLS integration for smart completions and diagnostics, an integrated GHCi REPL, structure view, Haddock docs, live templates, run configurations for Stack, Cabal and runghc. I also added sdk integration, so you can manage your haskell project version from the project structure view.

Anyway, this is just a first release. And what I really need right now is people who are willing to try and tell me what works and what doesn’t. I’m happy to hand out free voucher codes for a trial month to anyone here who wants to give it a go and share their experience. Just reply, dm me or reach out on GitHub and I’ll send one over.

Feedback and Feature wishes would be fantastic! And if you like the work, a quick review on the JetBrains marketplace would mean the world.

On pricing: I really want to make it accessible as possible, while still being able to commit to it. So it is free for open source projects and students, 50% off for non-profits and startups. But if none of that applies, just reach out anyway. At this stage I care a lot more about feedback than anything else.

Hope some of you find it useful. Let me know what you think :slight_smile:

P.S.: I am not sure about the policies of direct linking around here, so if anybody wants to share the link as a reply that would be amazing!

21 Likes

Nothing wrong about direct linking! In any case: Flexible Haskell

3 Likes

hey, that’s awesome. Thank you!

I might be missing something obvious, but what does this provide over using HLS with VSCode?

Glad you asked. First of all, it is a JetBrains IDE extension. There are many developers out there who prefer the JetBrains IDEs over VSCode (myself included) - for various reasons. It is not a competition, though, I personally think that more tools = better. Haskell should be on any IDE available, if you ask me and this just expands it to IntelliJ, PyCharm, GoLang etc…

Then there is the grammar itself. VSCode traditionally relies on TextMate grammars, which are regex-based. There is an alternative with Treesitter, but I am not sure if the vscode plugin uses that. That means the editor’s own understanding of your files is pretty much flat without the language server running. Ours is based on a BNF structure, which gives us an actual hierarchy. Things like auto-complete, on-hover documentation, validation, refactoring all come naturally because the underlying structure is already there. With VSCode you really depend on the language server for all of that, whereas for us HLS is just an addon on top (we do support using it, but do not rely on it). And once indexed, navigation and lookups are fast because the IDE indexes elements on the fly via its own PSI tree, independent of any external server.

Anyway, in terms of features, out of the box it should make it super easy for everyone to work with. There are still things left to improve (which is why i really want feedback - did I mention that?). But I think it makes an interesting addition. Give it a go :slight_smile:

5 Likes

I’ll try it.

With VSCode you really depend on the language server for all of that, whereas for us HLS is just an addon on top

Does that mean that your plugin provides on-hover documentation and auto-completion without necessarily relying on HLS? This might be a big deal. We have a relatively large project at work and sometimes it’s a pain to have to wait for HLS to load.

I tried it and it crashed IntelliJ entirely. In the logs I saw two exceptions. The project works fine in VSCode.

Exception 1:

Broken consistency: false
com.intellij.platform.workspace.storage.impl.exceptions.SymbolicIdAlreadyExistsException: Entity with symbolicId: SdkId(name=GHC 9.14.1, type=HaskellSdk) already exist
	at com.intellij.platform.workspace.storage.impl.MutableEntityStorageImpl.assertUniqueSymbolicId(ImmutableEntityStorageImpl.kt:282)
	at com.intellij.platform.workspace.storage.impl.MutableEntityStorageImpl.putEntity(ImmutableEntityStorageImpl.kt:249)
	at com.intellij.platform.workspace.storage.impl.ModifiableWorkspaceEntityBase.addToBuilder(Entities.kt:543)
	at com.intellij.platform.workspace.jps.entities.impl.SdkEntityImpl$Builder.applyToBuilder(SdkEntityImpl.kt:105)
	at com.intellij.platform.workspace.storage.impl.MutableEntityStorageImpl.addEntity(ImmutableEntityStorageImpl.kt:229)
	at com.intellij.workspaceModel.ide.impl.legacyBridge.sdk.SdkTableBridgeImpl.addNewSdk$lambda$5(SdkTableBridgeImpl.kt:81)
	at com.intellij.workspaceModel.ide.impl.GlobalWorkspaceModel.updateModel(GlobalWorkspaceModel.kt:114)
	at com.intellij.workspaceModel.ide.impl.legacyBridge.sdk.SdkTableBridgeImpl.addNewSdk(SdkTableBridgeImpl.kt:80)
	at com.intellij.openapi.projectRoots.impl.ProjectJdkTableImpl.addJdk(ProjectJdkTableImpl.kt:80)
	at com.ilscipio.language.haskell.sdk.HaskellSdkService.lambda$createSdkFromGhc$2(HaskellSdkService.java:292)
	at com.intellij.openapi.application.WriteAction.lambda$run$1(WriteAction.java:85)
	at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runWriteAction(AnyThreadWriteThreadingSupport.kt:389)
	at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runWriteAction(AnyThreadWriteThreadingSupport.kt:383)
	at com.intellij.openapi.application.impl.ApplicationImpl.runWriteAction(ApplicationImpl.java:907)
	at com.intellij.openapi.application.WriteAction.run(WriteAction.java:84)
	at com.ilscipio.language.haskell.sdk.HaskellSdkService.lambda$createSdkFromGhc$3(HaskellSdkService.java:290)
	at com.intellij.openapi.application.TransactionGuardImpl.runWithWritingAllowed(TransactionGuardImpl.java:236)
	at com.intellij.openapi.application.TransactionGuardImpl.access$100(TransactionGuardImpl.java:25)
	at com.intellij.openapi.application.TransactionGuardImpl$1.run(TransactionGuardImpl.java:198)
	at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runIntendedWriteActionOnCurrentThread$lambda$2(AnyThreadWriteThreadingSupport.kt:217)
	at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runWriteIntentReadAction(AnyThreadWriteThreadingSupport.kt:128)
	at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runIntendedWriteActionOnCurrentThread(AnyThreadWriteThreadingSupport.kt:216)
	at com.intellij.openapi.application.impl.ApplicationImpl.runIntendedWriteActionOnCurrentThread(ApplicationImpl.java:843)
	at com.intellij.openapi.application.impl.ApplicationImpl$2.run(ApplicationImpl.java:421)
	at com.intellij.openapi.application.impl.AppImplKt.rethrowExceptions$lambda$2(appImpl.kt:57)
	at com.intellij.util.concurrency.ChildContext$runInChildContext$1.invoke(propagation.kt:101)
	at com.intellij.util.concurrency.ChildContext$runInChildContext$1.invoke(propagation.kt:101)
	at com.intellij.util.concurrency.ChildContext.runInChildContext$lambda$2(propagation.kt:111)
	at com.intellij.util.concurrency.Propagation$runAsCoroutine$deferred$1.invokeSuspend(propagation.kt:283)
	at com.intellij.util.concurrency.Propagation$runAsCoroutine$deferred$1.invoke(propagation.kt)
	at com.intellij.util.concurrency.Propagation$runAsCoroutine$deferred$1.invoke(propagation.kt)
	at kotlinx.coroutines.intrinsics.UndispatchedKt.startCoroutineUndispatched(Undispatched.kt:27)
	at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:90)
	at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:123)
	at kotlinx.coroutines.BuildersKt__Builders_commonKt.async(Builders.common.kt:87)
	at kotlinx.coroutines.BuildersKt.async(Unknown Source)
	at com.intellij.util.concurrency.Propagation.runAsCoroutine(propagation.kt:278)
	at com.intellij.util.concurrency.ChildContext.runInChildContext(propagation.kt:111)
	at com.intellij.util.concurrency.ChildContext.runInChildContext(propagation.kt:101)
	at com.intellij.util.concurrency.ContextRunnable.run(ContextRunnable.java:27)
	at com.intellij.openapi.application.impl.AppImplKt.rethrowExceptions$lambda$3(appImpl.kt:68)
	at com.intellij.openapi.application.impl.LaterInvocator$1.run(LaterInvocator.java:102)
	at com.intellij.openapi.application.impl.FlushQueue.runNextEvent(FlushQueue.java:117)
	at com.intellij.openapi.application.impl.FlushQueue.flushNow(FlushQueue.java:43)
	at java.desktop/java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:318)
	at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:781)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:728)
	at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:722)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
	at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:87)
	at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:750)
	at com.intellij.ide.IdeEventQueue.defaultDispatchEvent(IdeEventQueue.kt:675)
	at com.intellij.ide.IdeEventQueue._dispatchEvent(IdeEventQueue.kt:573)
	at com.intellij.ide.IdeEventQueue.dispatchEvent$lambda$18$lambda$17$lambda$16$lambda$15(IdeEventQueue.kt:355)
	at com.intellij.openapi.progress.impl.CoreProgressManager.computePrioritized(CoreProgressManager.java:857)
	at com.intellij.ide.IdeEventQueue.dispatchEvent$lambda$18$lambda$17$lambda$16(IdeEventQueue.kt:354)
	at com.intellij.ide.IdeEventQueueKt.performActivity$lambda$2$lambda$1(IdeEventQueue.kt:1045)
	at com.intellij.openapi.application.WriteIntentReadAction.lambda$run$0(WriteIntentReadAction.java:24)
	at com.intellij.openapi.application.impl.AnyThreadWriteThreadingSupport.runWriteIntentReadAction(AnyThreadWriteThreadingSupport.kt:128)
	at com.intellij.openapi.application.impl.ApplicationImpl.runWriteIntentReadAction(ApplicationImpl.java:917)
	at com.intellij.openapi.application.WriteIntentReadAction.compute(WriteIntentReadAction.java:55)
	at com.intellij.openapi.application.WriteIntentReadAction.run(WriteIntentReadAction.java:23)
	at com.intellij.ide.IdeEventQueueKt.performActivity$lambda$2(IdeEventQueue.kt:1045)
	at com.intellij.ide.IdeEventQueueKt.performActivity$lambda$3(IdeEventQueue.kt:1054)
	at com.intellij.openapi.application.TransactionGuardImpl.performActivity(TransactionGuardImpl.java:109)
	at com.intellij.ide.IdeEventQueueKt.performActivity(IdeEventQueue.kt:1054)
	at com.intellij.ide.IdeEventQueue.dispatchEvent$lambda$18(IdeEventQueue.kt:349)
	at com.intellij.ide.IdeEventQueue.dispatchEvent(IdeEventQueue.kt:395)
	at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:207)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
	at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
	at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
	at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:92)
2026-03-18 13:11:32,090 [  10318] SEVERE - #c.i.p.w.s.i.MutableEntityStorageImpl - IntelliJ IDEA 2024.3.2.1  Build #IC-243.23654.153
2026-03-18 13:11:32,090 [  10318] SEVERE - #c.i.p.w.s.i.MutableEntityStorageImpl - JDK: 21.0.5; VM: OpenJDK 64-Bit Server VM; Vendor: JetBrains s.r.o.
2026-03-18 13:11:32,090 [  10318] SEVERE - #c.i.p.w.s.i.MutableEntityStorageImpl - OS: Linux
2026-03-18 13:11:32,090 [  10318] SEVERE - #c.i.p.w.s.i.MutableEntityStorageImpl - Plugin to blame: Flexible Haskell version: 2026.1.0

Exception 2:

13:14:05,826 [ 164054] SEVERE - #com.ilscipio.language.haskell.lsp.HaskellLanguageServer - Failed to start HLS
java.lang.NullPointerException: Cannot invoke "java.lang.Process.isAlive()" because "this.serverProcess" is null
	at com.ilscipio.language.haskell.lsp.HaskellLanguageServer.start(HaskellLanguageServer.java:132)
	at com.ilscipio.language.haskell.lsp.HaskellLanguageServer.handleCrash(HaskellLanguageServer.java:482)
	at com.ilscipio.language.haskell.lsp.HaskellLanguageServer.readServerOutput(HaskellLanguageServer.java:377)
	at java.base/java.lang.Thread.run(Thread.java:1583)
2026-03-18 13:14:05,827 [ 164055] SEVERE - #com.ilscipio.language.haskell.lsp.HaskellLanguageServer - IntelliJ IDEA 2024.3.2.1  Build #IC-243.23654.153
2026-03-18 13:14:05,827 [ 164055] SEVERE - #com.ilscipio.language.haskell.lsp.HaskellLanguageServer - JDK: 21.0.5; VM: OpenJDK 64-Bit Server VM; Vendor: JetBrains s.r.o.
2026-03-18 13:14:05,827 [ 164055] SEVERE - #com.ilscipio.language.haskell.lsp.HaskellLanguageServer - OS: Linux
2026-03-18 13:14:05,827 [ 164055] SEVERE - #com.ilscipio.language.haskell.lsp.HaskellLanguageServer - Plugin to blame: Flexible Haskell version: 2026.1.0

It sure does. And I can extend on it. So i can do fun stuff like mass refactoring or give you tiny helper functions here and there. So definitely try it out!

If it is not working ootb or if there is something missing let me know - I am quite fast with fixes usually.

Interesting. Did you have LS running at that point? Did you set something in the settings? And are you using Linux/macOS or Windows?

Give me a few minutes - I’m out for lunch but I’ll work on the fix once I am back at my desk!

I just launched idea from a shell inside the project’s folder, like I do with code. This is on Ubuntu 24.04 LTS.

Once the plugin starts loading it blocks the whole IDE after showing me the exception.

1 Like

Unfortunately, it doesn’t work on my Macbook M3 Max - I created an issue on GitHub Stuck in HLS: Initializing... · Issue #1 · ilscipio/flexible-haskell-jetbrains-plugin · GitHub

1 Like

Thanks for that. Let me work on both - I am back at my desk now and taking a look!

P.S.: Kudos on the detailed bug report. That is amazingly helpful.

Holy cow, thank you a lot! Now the best IDE in the world got the best programming language supported and with a bang at that!

1 Like

I love you!

But beware: it is a first release and I am already working on bugfixes. So report anything you can find and let me know what you miss. Eager to improve!

Maybe I would mark it as Beta/Preview/something similar in the Marketplace (if it has such an option) and make it free until the major bugs are resolved - just my thoughts :slight_smile:

2 Likes

Unfortunately, there is no such thing. You are either out or not. You can add a beta channel to the release cycle, but that’s different.

I did add a message in bold though stating the same and usually I think it should be clear that a first release is a first release.

But give me a few hours to fix the bugs you reported. Both yours and @dnikolovv have the same issue - it relates to how i start/stop the LS, I messed up the way paths are constructed on linux vs windows machines. Fix incoming :wink:

That said: happy to hand out voucher codes to anyone reporting bugs and sending me feedback here. Just dm me for it, please :slight_smile:

1 Like

Ok, no problems :slight_smile: And I’ve just added another bug :beetle:

1 Like

Keep em coming. I will send you all a download link from the marketplace shortly, so you can check the 2026.1.1 (if you are willing to). It otherwise takes JetBrains up to 48hrs to approve the update.

Also: make sure to dm me for a voucher code (either a free month or a discount) - in case you are not already getting the 100% one from JetBrains.

Worth noting:
JetBrains has various discount programs available that many of you probably can take advantage of:

  1. Free JetBrains Student Pack (all academic workers get these)
  2. Licenses for Open Source Development
  3. One for startups etc

I am actively supporting all of them with my plugin, so the discounts are automatically applied on checkout if you are part of the program


Update: I am blocked posting for the next 21hrs or so (new account), so please reach out on github. I will still be checking here and answer as quickly as I am allowed to. Or perhaps start updating this comment :wink:


Update 2: 2026.1.1 with bugfixes is making its way to JetBrains

Thanks mirovarga , develop7 and @dnikolovv for reporting!

2 Likes

Just a quick heads up: I’m working on some grammar fixes - those created a few bugs that were reported on github. I will post an update asap.

@madppiper I’m really happy that you undertook this work. I might reinstall IDEA just to give it a try. :wink:

2 Likes