I must say I’m a bit surprised by the direction of this discussion. There are a few things that confuse me. Firstly, people seem to have a clear idea of a delineation between functional code and imperative code. What is it? I don’t know! It’s not clear to me that those two concepts are disjoint. Secondly, people seem to have the idea that imperative code is somehow “worse” than functional code. Why? I don’t know! To me Haskell is the world’s finest imperative programming language. I have no qualms about programming imperatively (only about programming with unrestrained effects). Thirdly, people seem to believe that Haskell can’t express the same ideas as the nice Python code. It can! Look below; it’s almost a direct translation of of the Python into the Haskell.
There are a couple of caveats in the translation. Firstly, the Haskell data structure is immutable, meaning that we have to explicitly replace the old one with the new one. That adds a couple of lines. Secondly, Haskell is pure, meaning that we have to get the counter in a separate step from using the lesson counter. That adds another couple of lines.
Often, writing in Haskell the same code that you would have written in Python is the right thing to do! I wish Haskellers would do so more.
sections' :: [Section Int]
sections' = flip evalState initialCounter $ do
for sections $ \section -> do
when (resetLessonPosition section) $
lessonCounter .= 1
lessons' <- for (lessons section) $ \lesson -> do
lessonCounter' <- use lessonCounter
let lesson' = lesson {lposition = lessonCounter'}
lessonCounter %= (+ 1)
pure lesson'
sectionCounter' <- use sectionCounter
let section' = section {sposition = sectionCounter', lessons = lessons'}
sectionCounter %= (+ 1)
pure section'
Full code: Solution to https://discourse.haskell.org/t/beautiful-functional-programming/7411 · GitHub