Haskell Libraries I Love

I just wanted to share some of my favorite Haskell libraries, and why I love them. Most of my projects use most of these libraries.

relude: Alternative Prelude

More convenient

  • Re-exports common types, type classes, and functions from base, containers, text, bytestring, etc.
    • Types: Text and LText, ByteString and LByteString, etc.
    • Type classes: Alternative, MonadIO, Generic, etc.
    • Functions: traverse_, when, fromMaybe, etc.
  • Provides extra utility type classes and functions
    • Type classes: One, ToText, ToString, ConvertUtf8, etc.
    • Functions: whenM, whenJust, etc.
  • Prefers Text over String
  • Lifts IO functions to MonadIO

More correct

  • No partial functions
    • head works on NonEmpty a
    • readMaybe instead of read
    • etc.

unliftio: Extended standard library

More convenient

  • Re-exports types and functions from base, async, bytestring, directory, process, stm, etc.
  • Lifts IO functions to MonadIO
  • Lifts IO functions taking IO arguments to MonadUnliftIO
    • base: withFile :: FilePath -> IOMode -> (Handle -> IO r) -> IO r
    • unliftio: withFile :: MonadUnliftIO m => FilePath -> IOMode -> (Handle -> m a) -> m a
  • Consistent module naming scheme (UnliftIO.{Async,Directory,Process,STM,etc.})

More correct

  • Monads implementing the MonadUnliftIO type class don't discard monadic state (more info)
  • Doesn't catch async exceptions (more info)
  • Uses uninterruptible masking for bracket's cleanup handler (more info)
  • Doesn't re-export unsafe functions like readFile (more info)

More performant

  • Provides the Conc type, a more efficient alternative to async's Concurrently that forks fewer threads

streamly: Streaming and concurrency

  • Extremely efficient, highly optimized internals
  • Straightforward/boring API, no confusing type-level programming or poor type inference
  • Represents a stream as data which is transformed using combinators, instead of composing a pipeline of stream transformation functions
  • Provides composable Fold and Unfold types - inspired by the foldl library - for producing and consuming streams, respectively
  • Streams can be produced, transformed, and consumed concurrently (you can completely replace async with streamly, more info)

optics: Alternative lens

  • Abstract interface makes for much nicer type errors and easier to read documentation
  • Comes with generic-lens-style OverloadedLabels functionality out of the box
  • Smaller dependency footprint, faster compile time

witch: Rust's From and TryFrom traits in Haskell

  • The convenience of relude's ToText/ToString/ConvertUtf8/etc. conversion type classes, applied to all types
  • Very simple API (just call into @YourType or tryInto @YourType)