Backstory:
So I know the somewhat very basics of haskell, and for a small program that I wanted to do I found a function in a library (the function was chunksOf
form Data.List.Split
, which was it's own confusing thing since for the looks of it the package name is split
).
So I tried to look for a package manager, which lead me to stack. Now I tried to work with it but I don't want to build a massive project, I just want to experiment around a bit.
Confusion:
- I do not understand the whole project structure (there is a lot of indirection and I can't tell even to which file I should be writing my code, it's a small thing I only want one file and one function from one lib).
- Why is there not a simple package installer alternative, I feel the tool is getting in my way more than it's helping.
- I find that this is more of a general haskell thing but I do agree that although it's hard documentation is good the soft one is lacking and I think it's what I'm feeling now. # TL;DR: I don't understand stack
PS: Sorry if this is too long this is my first post, I'm not sure how this works
Top comments (2)
EDIT: I just see you posted this a while ago. So you most probably figured things out by now 😅
Hi :)
Disclaimer #1: I'm not good at #explainlikeimfive but I'll give it a try.
Disclaimer #2: I'm not a an expert on stack just basically use it for the same reasons as you mention.
That's indeed confusing at first. Haskell modules follow (most of the time) a convention for the names. Eg. since the
split
package contains functions for splitting lists it defines the moduleData.List.Split
. A package might define many modules. To learn more about modules check out the first and last sections here.There are templates for creating projects with Stack, maybe you can find one with the bare minimum. The default one indeed looks like there's a lot going on, but once you are familiar with it you'll be fine.
Another thing that is confusing at first 😅 But bare with me, it'll make sense. Stack creates sandboxed projects, in other words your project will have all the dependencies vendored to it and even it's own version of the compiler (this way different projects can have different dependencies and compiler versions). There are ways to install dependencies globally and ignore stack but eventually that becomes a problem because things won't work with each other.
I assume you installed stack already. To create a project with the default template you can run:
That might take a bit of time to complete. It downloads a version of the compiler (if you don't have it already) for the project and sets up all the directories/files. Which should look something like this:
You can ignore most of it. There are only a few files you'll care about. But don't remove them, some are still needed by stack.
These are the ones you'll be using now.
package.yml
Here you configure the dependencies, modules, and a bunch of other things like default compiler options. For now the only thing you have to do is add the
split
package so Stack can download it. It will look something like this:Most of the time the version isn't needed, Stack knows which one is the right one.
You can ignore the rest inside
package.yml
for now. But if you want, feel free to play around and see how things break and what you can do with it.After you add a package in dependencies you'd need to run either
stack build
,stack run
orstack ghci
. Stack will figure out there's a new dependency and download it.IMPORTANT: don't run
stack install split
. That will install the package globally. But what you want is have it locally in your project.app/Main.hs
This is the file that will produce the executable program.
Here you define the
main :: IO ()
function that runs when you execute the program (like C++'s main). Stack already defined it for you. If you want, you can ignore what's insrc/
and write all your code in this file.src/Lib.hs
This is the library code. Stack will treat any file inside
src/
as a module.Module names need to match the file path/name. So
src/Lib.hs
defines theLib
module. Which can be imported inapp/Main.hs
. Stack takes care of that.Normally the
src/
directory is where you'd write your code and have the bare minimum inapp/Main.hs
to run your program.Useful commands
There are a few Stack commands that are useful at first.
This runs the REPL. Stack takes care of importing your modules here, so you can for example call
main
directly.Also as I mentioned, running this command will first install the new dependencies that were added to
package.yml
. If you add one while the REPL is already running you'll have to run the REPL again.This will compile and execute your program. In other words run the
main
function fromapp/Main.hs
.Also installs dependencies before compiling.
In case you only want to compile run that one ☝️
If you want to have your project available globally as a executable you can install it.
There's a lot of information about the Stack CLI there. Might also be useful.
I hope that was useful :)
Feel free to join the Functional Programming Slack. There's a channel for those of us that are learning Haskell (#haskell-beginners), you can ask questions like this one there. People is quite welcoming and will help you :)
Also, here are a few links that will help on getting stared with Stack:
And make sure to check the Stack documentation as well.
Happy and safe coding 🎉
Actually I hadn't, I don't have experience with build tools like stack. I'm familiar with npm so the logic of having to compile before the tool downloads my packages is somewhat foreign to me.
Also my experience with app templates is also lacking. So finally having some understanding of the directory structure helps.
This comment helps me a lot thank you very much. 😄