Hacker News new | ask | show | jobs
by cosmic_quanta 646 days ago
I have also initially struggled with structuring Haskell programs. Without knowing anything about what you want to do, here's my general approach:

1. Decide on an effect system

Remember, Haskell is pure, so any side-effect will be strictly explicit. What broad capabilities do you want? Usually, you need to access some program-level configuration (e.g. command-line options) and the ability to do IO (networking, reading/writing files, etc), so most people start with that.

https://tech.fpcomplete.com/blog/2017/06/readert-design-patt...

2. Encode your business logic in functions (purely if possible)

Your application does some processing of data. The details don't matter. Use pure functions as much as possible, and factor effectful computations (e.g. database accesses) out into their own functions.

3. Glue everything together in a monadic context

Once you have all your business logic, glue everything together in a context with your effect system (usually a monad stack using ReaderT). This is usually where concurrency comes in (e.g. launch 1 thread per request).

---

Beyond this, your application design will depend on your use-case.

If you are interested, I strongly suggest to read 'Production Haskell' by Matt Parsons, which has many chapters on 'Haskell application structure'.

2 comments

> 1. Decide on an effect system

This shouldn't even be proposed as a question to someone new to Haskell. They should learn how monad transformers work and just use them. 90% of developers playing around effect systems would be just fine with MTL or even just concrete transformers. All Haskell effect systems should be considered experimental at this point with unclear shelf lives.

Everything else you said I agree with as solid advice!

> This shouldn't even be proposed as a question to someone new to Haskell. They should learn how monad transformers work and just use them. 90% of developers playing around effect systems would be just fine with MTL or even just concrete transformers. All Haskell effect systems should be considered experimental at this point with unclear shelf lives.

This is highly debatable. I would say that the effect systems effectful and Bluefin are actually significantly simpler than MTL and transformers, particularly as soon as you need to do prompt resource cleanup.

Personally I'd say that if newbies should start with naked IO and then switch to effectful or Bluefin once they've realised the downside of IO being available everywhere.

> All Haskell effect systems should be considered experimental at this point with unclear shelf lives.

effectful and Bluefin are here to stay. I guarantee it. For non-IO-based effect systems (e.g. polysemy, freer-effects) I agree.

(Disclaimer: I'm the author of Bluefin)

> effectful and Bluefin are here to stay. I guarantee it. For non-IO-based effect systems (e.g. polysemy, freer-effects) I agree.

Just to be clear I think Bluefin is really cool and I'm a fan of your work overall.

I'm speaking from the industry/production perspective here. When polysemy and freer-effects were released there was a similar belief that they were here to stay.

transformers and MTL have stood the test of time, are heavily documented, and are pervasive throughout Hackage. Understanding them and how to build programs with them is essential for anyone trying to break into 'production haskell' as a career move.

> Just to be clear I think Bluefin is really cool and I'm a fan of your work overall.

Thanks!

> I'm speaking from the industry/production perspective here. When polysemy and freer-effects were released there was a similar belief that they were here to stay.

Well, from my perspective, I've never worked at a place that's used polysemy of freer-effects.

> transformers and MTL have stood the test of time, are heavily documented, and are pervasive throughout Hackage. Understanding them and how to build programs with them is essential for anyone trying to break into 'production haskell' as a career move.

Sadly true.

> Well, from my perspective, I've never worked at a place that's used polysemy of freer-effects.

I have with another deprecated effect library. Its a bummer to have something so core to the architecture that is deprecated but then to not have the time or buy-in to do anything about it.

That does sound like a bummer. To add some explanation, to explain why I said that effectful and Bluefin are here to say, it's because they're based on IO, so it's easy to get them to interoperate, and if in the future a new "EffectSystemX" comes along, also based on IO, then they will interoperate with that too. Thus the risk of them being deprecated is minimal.

I haven't published my effectful-Bluefin interoperation layer, but you can see it here:

https://github.com/tomjaguarpaw/bluefin/blob/caa59700d910c76...

Someone truly new to Haskell shouldn't use it professionally.

Once you've learned what is necessary to, say, modify already-existing applications, you should be familiar with monads and some basic monad transformers like ReaderT.

Once you're there, I don't think 'choosing an effect system' is a perilous question. The monad transformer library, mtl, is an effect system, the second simplest one after IO.

The original poster said they want to use Haskell professionally but that they are struggling to understand how to structure programs.

> Once you're there, I don't think 'choosing an effect system' is a perilous question. The monad transformer library, mtl, is an effect system, the second simplest one after IO.

I'm aware of that, generally when people say "choose effect system" they mean choose some algebraic effect system, all of which (in Haskell) have huge pitfalls. The default should be monad transformers unless you have some exceptional situation.

> generally when people say "choose effect system" they mean choose some algebraic effect system

This isn't really true. Bluefin and effectful are effect systems, but not algebraic effect systems.

On a software engineering level choosing such unusually deep-reaching libraries unusually soon in the development of a program is a major but uninformed commitment, a dangerous bet that more practical programming languages try to avoid imposing on the user.
I realize I didn't mention monad transformers at all in my original post, I only linked to them!

I should have mentioned that, as you say, monad transformers should be the default effect system choice for 99% of people

This is excellent advice that unfortunately seems to get lost in a lot of Haskell teachings. I learned Haskell in school but until I had to use it professionally I would have never been able to wrap my head around effect systems. I still think that part of Haskell is unfortunate as it can get in the way of getting things done if you're not an expert, but being able to separate pure functions from effectful ones is a massive advantage.