We've finally completed 1% of the challenge, 99% to go. I must admit, so far it's the most fun I've had in a very long time.
A Little Anecdote
Before we can jump into the coding and never come back, there is one more thing we need to do. Remember when the authors of Learn You a Haskell for Great Good! falsely assumed that there is no way we wouldn't be ready to jump right into coding?
[...] You probably already have your favorite text editor installed so we won’t waste time on that.
It turns out they were so wrong. I am currently doing all the learning and the recordings on my gaming computer, just because of the livestreams that I want to do from time to time. The problem with this PC was that it used to run Windows. At one point I even had a working setup with NixOS and WSL2 running. I was able to game, and I was able to code. I was hooking the VS Code Windows frontend into the VS Code server running in my WSL2 machine. Honestly, it wasn't that bad and way better than any macOS virtualization integrations that necessarily require XQuartz to display any GUI from the vm on the host system.
Well, it turns out after my motherboard melted recently, Microsoft decided to brick my OEM key and my active and valid Windows license. There was no way back into the game for me, except buying another license. And I need Windows Pro, because of the Remote Desktop features. Short story long, I decided to turn my back on Microsoft once and for all and go with a linux gaming distro. So here we are, with Bazzite, an immutable Fedora Atomic Desktop distro. And have you ever tried installing a piece of software in here? Well I've used NixOS... And Fedora Silverblue feels way more painful and unstable simultaneously.
Choice made, we're sticking with it. Let's get used to those distroboxes and whatever else comes with it. It's a funny concept in the end and reminds me a lot about WSL2.
One More Thing
I have tried a few things, and honestly, for me it is impossible to get VS Code running on my Bazzite OS. So let it be, I've always been kind of an amateur and secret admirer of Vim anyways. While you are eating your Sunday cake with your familiy, I am sitting in my dark room, fingers on the keyboard, glazing at my screen. Playing my favorite game: vimtutor.
Jokes aside, let's commit to Neovim, in my opinion this sounds like the only valid option here.
And we have to be honest to ourselves here. This whole challenge is about fun. Is Vim fun? Hell yes, it is. Is it going to make us progress faster? Definitely not. But here is the idea: We are starting to learn new programming concepts and paradigms from scratch. In conclusion one thing is safe to assume - We won't produce a lot of code at the beginning. We won't need a lot of features that some IDE or other text editor might bring into the ring. There will never be a better time than now to setup and use Neovim. As we progress through the challenge we will have to keep pace with our editor, obviously. But this is true for any other editor too. And as far as I know (Neo)vim supports language servers and we have seen on day one that GHCup brings one out of the box. And the little demon sitting on my shoulder keeps whispering
Rick. You will be fine. Just do it. Now.
Neovim in Bazzite
Awkward combination of productivity guru and procrastinator. Suits me, I like it.
For the installation I am given 3 options:
- Install from download
- Install from package
- Install from source
My first intuition would be to go with the Flatpak version, if there hadn't been this little note
Note that Flatpak’ed Neovim will look for init.vim in
~/.var/app/io.neovim.nvim/config/nviminstead of~/.config/nvim.
Not a big deal, but I know that in 10 days I will be confused because of this. I remember setting up Neovim on my Mac, and the whole documentation was like always referring $XDG_CONFIG_HOME. I didn't know what that was back then and it took me some time figuring out that it basically just meant ~/.config in unix systems. So, as I am traumatized and love to stick to defaults the Flatpak'ed version never was an option. Let's do it as vanilla as we can, and when in doubt just think about how much your future self will appreciate you not being a jerk to them.
So let's go with the AppImage package this time, as dnf isn't an option for a read-only distro.
Install Neovim
We follow Neovims instructions from the AppImage installation method. As we are using a x86_64 system we download the appropriate AppImage, otherwise we can just replace it with arm64
cd ~/Downloads
curl -LO https://github.com/neovim/neovim/releases/latest/download/nvim-linux-x86_64.appimage
chmod u+x nvim-linux-x86_64.appimage
sudo mkdir -p /opt/nvim
sudo mv nvim-linux-x86_64.appimage /opt/nvim/nvim
echo 'export PATH="$PATH:/opt/nvim/"' >> ~/.zshenv
source ~/.zshenv
It already feels like a bad choice after doing these steps. Let's stick to it and think of a nicer way to install it later.
Setup the Haskell Language Server
On day one we skipped an essential part: the installation of the Haskell language server. Let's do this now. Remember we did this in our distrobox to not pollute the host environment with things we might not yet understand. So back into the distrobox and we run the GHCup installer again.
distrobox enter haskell-test
curl --proto '=https' --tlsv1.2 -sSf https://get-ghcup.haskell.org | sh
#<Enter> to start the installer
#<Enter> to confirm all dependencies are installed
#GHCup provides different binary distribution "channels". First, we select the base channel.
#[K]<Enter>
#Detected bash shell on your system...
#[P]<Enter>
#Do you want to install haskell-language-server (HLS)?
#[Y]<Enter>
#Do you want to enable better integration of stack with GHCup?
#[Y]<Enter>
Done. Language Server enabled. Next, let's wire it up.
Enable the Language Server in Neovim
Neovim has great language server support out of the box. The HLS documentation recommends using either haskell-tools.nvim or nvim-lspconfig. As the first brings its own LSP server and we've already went through the installation of the one coming with GHCup, I decided to install nvim-lspconfig to get started. Keeping things minimal.
Nvim-lspconfig is a minimal collection of hundreds of lsp server configurations and requires only to enable them.
Let's install the plugin in Neovim using vim pack. Let's jump straight into our ~/.config/nvim/init.lua and add these lines
vim.pack.add{
{ src = 'https://github.com/neovim/nvim-lspconfig' },
}
And now just enable the preset defaults for HLS that are shipped with the plugin.
vim.lsp.enable('hls')
That's it, now let's just open a file, let's say test.hs and try it out, as soon as we are encountering the first error the line gets marked with an "E". Now to see the entire error message, we still have to enable the diagnostics which are disabled by default in Neovim.
Enable Diagnostics and Final init.lua
To see the error messages inline in Neovim, we have enable them using the correct diagnostics settings in our ~/.config/nvim/init.lua
vim.diagnostic.config({
virtual_lines = { current_line = true },
virtual_text = false,
signs = true,
})
And now when hovering the line with the error we can see the whole message our LSP returns in one or multiple virtual lines. Directly inside of Neovim.
And here is the final config of our ~/.config/nvim/init.lua to show everything together.
vim.pack.add{
{ src = 'https://github.com/neovim/nvim-lspconfig' },
}
vim.lsp.enable('hls')
vim.diagnostic.config({
virtual_lines = { current_line = true },
virtual_text = false,
signs = true,
})
And that's it. Now we are ready to start Haskell on Day 4! 🎉
See you tomorrow!
Take care!
Rick.