this post was submitted on 02 Jul 2023
197 points (94.6% liked)

Programmer Humor

19515 readers
314 users here now

Welcome to Programmer Humor!

This is a place where you can post jokes, memes, humor, etc. related to programming!

For sharing awful code theres also Programming Horror.

Rules

founded 1 year ago
MODERATORS
 
you are viewing a single comment's thread
view the rest of the comments
[–] zygo_histo_morpheus 26 points 1 year ago (2 children)

A monad isn't "a thing", it's a common interface shared by several different types that have a common mathematical structure that happens to be useful for structuring programs around. I think that's why it's so confusing to people, other programming languages tend to not have as abstract abstractions front and center.

[–] [email protected] 4 points 1 year ago (2 children)

In my experience they're only really in your face when you're doing things with side-effects, and at that point it's just a lobster trap that collects you non-functional code until you pass it to main. Maybe I'm just a lame Haskeller though.

[–] zygo_histo_morpheus 3 points 1 year ago (1 children)

I use Either (for error handling) and State (for shared state in the program) fairly often, sometimes both at once with IO in a monad transformer stack. Having pure code is of course the best but error handling at least tends to sneak in through the program

[–] [email protected] 3 points 1 year ago (1 children)

monad transformer stack

I'm going to have to look that up.

When you write big Haskell programs, do you ever find yourself emulating imperative code? I always do past a certain point, and then I figure I might as well bite the bullet and just move to Rust or C or something for the extra performance.

[–] zygo_histo_morpheus 2 points 1 year ago (1 children)

Monad transformers are monads that take another monad as a type argument and are for when you want to have severtal kinds of Monads at the same time. If you want to be able to throw errors, have state and perform IO you can use the type ExceptT ErrorType StateT StateType IO a for example.

IMO the biggest strengths of Haskell are that you can create very powerfull abstractions and that you have a greater ability to reason about your code. This is still true to some extent even if you have a lot of imperative-like State or IO code, so it can still valuable to write in Haskell. Of course, it's still good to avoid this when possible, and take it as a sign to rethink your design.

The main reasons why I don't program more in Haskell are that it can be un-ergonomic to write certain kinds of code (that use IO a lot for example), that it can be hard to reason about space leaks and primarily that it's basically pointless to convince anyone else at $DAYJOB that writing something in Haskell is a good idea (for not entierly bad reasons, it's good to have code that's maintainable by multiple people)

[–] [email protected] 2 points 1 year ago* (last edited 1 year ago) (1 children)

I wasn't even thinking of IO - I'm very good at avoiding that when possible - what I end up doing is writing giant functions like bigChungus :: a -> a where a is a large agglomeration of mostly auxiliary data, and then I call iterate on it to search for a member of [a] signifying completion, often with a version of find. If you think about it that's just a loop with the parts of a working as mutable variables.

I have to be suspicious that GHC runtime is actually building such a linked list and not turning that back into a loop in the imperative assembly code, like it should. And really, if I'm writing that way why Haskell.

[–] zygo_histo_morpheus 2 points 1 year ago (1 children)

Hmm no, I can't say that I've ever writen code like that. For one, it might be better to use loop :: (a -> Either a b) -> a -> b instead so that you don't have to sort through the result afterwards with find.

I'm not sure exactly what you're trying to do, but maybe using the State monad could be a good idea? If a is an object with fields that you want to be able to read and update that sounds a bit like what you might want to use State for. This can be combined with maybe something from the loop section of Control.Monad.Extra to make the intention of the code a bit clearer.

If performance is critical you might be better of using a different language anyway (Haskell performance is okay but not amazing) but otherwise I don't think that this is really gonna slow down your code unacceptably much.

[–] [email protected] 2 points 1 year ago

Hmm no, I can’t say that I’ve ever writen code like that. For one, it might be better to use loop :: (a -> Either a b) -> a -> b instead so that you don’t have to sort through the result afterwards with find.

Lol. Yep, I'm a lame Haskeller.

I’m not sure exactly what you’re trying to do, but maybe using the State monad could be a good idea?

This is a pattern that has repeated on different things, and the main reason I haven't done much Haskell in the past couple years. Maybe State is what I need, I'll have to look into it.

If performance is critical you might be better of using a different language anyway (Haskell performance is okay but not amazing) but otherwise I don’t think that this is really gonna slow down your code unacceptably much.

See, I come from a maths background, and I have a bit of perfectionism going even if it's not a big deal. Maybe the processor can do a stupid thing and get away with it, but why should it?

What's that? Valuable programmer time you say? Pffft. I'll be over here designing a chess predicament with a multiply-infinite but well-defined solution to reach check (Yes, I've seen it done).

[–] [email protected] 1 points 1 year ago (1 children)

I mean, List is a monad. It just happens that the mathematical pattern works well for encapsulating side effects too.

[–] [email protected] 2 points 1 year ago

Oh, I know, it's just not in-your-face. It's entirely possible to use Lists without knowing that.

[–] [email protected] 2 points 1 year ago

I'm glad there is at least one serious answer on this thread.