• zygo_histo_morpheus@programming.dev
    link
    fedilink
    arrow-up
    1
    ·
    1 year ago

    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

    • CanadaPlus@lemmy.sdf.org
      link
      fedilink
      arrow-up
      1
      ·
      1 year ago

      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@programming.dev
        link
        fedilink
        arrow-up
        1
        ·
        1 year ago

        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)

        • CanadaPlus@lemmy.sdf.org
          link
          fedilink
          arrow-up
          1
          ·
          edit-2
          1 year ago

          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@programming.dev
            link
            fedilink
            arrow-up
            1
            ·
            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.

            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.

            • CanadaPlus@lemmy.sdf.org
              link
              fedilink
              arrow-up
              1
              ·
              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).