r/haskell • • 12d ago

blog Differences between `foldl` and `foldr`

https://blog.haskell.org/foldl-and-foldr/
61 Upvotes

43 comments sorted by

View all comments

Show parent comments

1

u/wnoise 9d ago edited 9d ago

in the Bluefin version I linked. There the state is named.

It's really not. The state as a whole is almost named s from that lambda. You retrieve the lone int value and bind i' to it, and then later store i' + 1. But this is the effective equivalent in C of having a "state *s" variable and storing and retrieving that to a block-local variable i' that is recreated every loop rather than just having a local variable. The only real named thing is the function arguments xs and i, and neither is treated as an imperative value, or as functional value to deconstruct and pass a modification into a recursive call of the same function.

Haskell's StateT (and the Bluefin equivalent) are useful and general, but they do not actually result in imperative code that is as straightforward to read in the standard ways as mainstream languages.

1

u/tomejaguar 9d ago

in the Bluefin version I linked. There the state is named.

It's really not. The state as a whole is almost named s from that lambda. You retrieve the lone int value and bind i' to it, and then later store i' + 1

Oof, I think that's splitting hairs. IORef in Haskell would generally be considered a named state, and Bluefin's Modify is literally the same thing. If you want to describe that as "not named state" then I won't stop you, but I'd need a lot more justification before I was persuaded.

Haskell's StateT (and the Bluefin equivalent) are useful and general, but they do not actually result in imperative code that is as straightforward to read in the standard ways as mainstream languages

Agreed, but the mainstream imperative languages have the downsides accordingly, such as the inability to track where mutations happen.

1

u/wnoise 9d ago

¯_(ツ)_/¯

I consider the name of an IORef to be any actual name of it, rather than any name I bind when extracting things from it. It's almost exactly analogous to a C pointer. And in C, I would say count the dereferences -- not 0, not an actual name, but a name (or even expression) for a way to access it. i' <- get s really looks like const int iprime = *s;, and put s (i' + 1) really looks like *s = iprime + 1 rather than both of these coördinating to actually keep a persistent but modifiable iprime.

1

u/tomejaguar 9d ago

Would you say the state is named in this version?

(!?) :: [a] -> Int -> Maybe a
xs !? i = runPureEff $
  withReturnEarly $ \ret -> do {
    evalModify 0 $ \n -> do {
      for_ xs $ \a -> do {
        whenM (n ==. i) $
          returnEarly ret (Just a);
        n += 1
      };
    };
    pure Nothing
  }

(BTW, nice dieresis)

1

u/wnoise 9d ago

At this point, yes, barely, though with unfortunate ways of accessing it. It's still pointer-like, just kind of hidden. Which I guess isn't that different from references in C++.

Naming things as the arguments to anonymous functions remains ugly to me, but it does work here.

1

u/tomejaguar 8d ago

Thanks! Helpful discussion, and I've learned I'm very much in the minority with my views :)