In recent months, I’ve started looking deeper into FP, looking at concepts like monad transformers and the State and Reader monads.

I initially did this by digging further into FSharpPlus, a library that enables more advanced FP in F#. That’s been a fine approach for the most part, but I gradually found myself referring to both F# and Haskell articles online to better grok the concepts.

Over time, I decided there would be value in just studying directly in Haskell itself, where the concepts are (I believe it’s fair to say) implemented more purely without the idiosyncrasies and limitations of .NET. I’ve been reading through the PDF version of the Haskell book on Wikibooks, going through at slow pace in my free time. (There’s no rush, after all. I might make this a lifelong project.)

Ultimately, though, you can only learn so much from just reading, so I’ve been trying to practice more with Haskell code.

I’m currently working in a new practice repo (days-away) on a very simple Haskell console application that takes a CSV of dates and descriptions and prints out the number of days since, or until, each date. (I’ve done this before in C#.) It’s basic stuff, but actually coding in Haskell is definitely helping me understand the concepts more, and through this project I’ve been able to get some basic experience with monad transformers. (It’s still tricky to understand which context I’m at times, but I’m improving.) I avoid LLMs for code generation (as the point here is to learn), but they are quite helpful for unblocking me when I get stuck.

Here’s the current version of my main function:

main :: IO ()
main =
    runExceptT computation >>= either putStrLn return
    where
        computation :: ExceptT String IO () = do
            fileName <- checkArgs
            checkExtension fileName
            content <- readSmallFile' fileName
            let lines_    = T.lines content
                lineCount = show $ length lines_
                charCount = show $ T.length content
                results   = traverse (runExceptT . parseLine) lines_
            liftIO $ do
                putStrLn $ "This file has " ++ lineCount ++ " line(s) and " ++ charCount ++ " character(s)."
                (errors, summaries) <- partitionEithers <$> results
                printSummaries summaries
                printErrors errors

It’s undoubtedly not great Haskell, but I’m pretty pleased I’ve been able to put something like this together and look forward to tweaking it more.


<
Previous Post
Ruby: Resolving NoMethodError - undefined method 'collect' error during CSV creation
>
Blog Archive
Archive of all previous blog posts