App-centric Monad-transformer based on Scala ZIO (UIO + ReaderT + ExceptT).
|LTS Haskell 20.15:||0.1.0.2|
|Stackage Nightly 2023-03-20:||0.1.0.2|
|Latest on Hackage:||0.1.0.2|
Module documentation for 0.1.0.2
A small monad-transformer analogue to the Scala ZIO library (basically, UIO + Reader + Either/ExceptT).
I like to call
ZIO a best-practices monad for applications. It
wraps in a
Reader monad for carrying around configuration and
environment data, and slightly more controversially, makes
error-handling more explicit by making all recoverable
exceptions and errors part of the return-type of functions.
Note that this is meant to provide the same basic functionality of the
While I’m not immediately looking into other features of ZIO-the-library, such as
concurrency, I welcome suggestions via issues or pull requests.
Comparison to other Haskell libraries
- UIO This ZIO library
builds upon UIO (Unexceptional-IO) as a dependency, and it is the
inner-most monad in the transformer stack. We use UIO, in conjunction
ExceptT, to model possible error states (or the lack thereof) more explicitly. In other words, we are trying to make all errors or exceptions. checked exceptions, where possible. See the blog post (or backup) for more details.
IO, but somewhat like Scala ZIO, provides much additional functionality, and providing much of that functionality
will be a goal of haskell-zio as well.
- Trio has essentially the same goals
as ZIO (and I believe it is isomorphic to ZIO), but is a self-described
experiment at the moment. The major experimental aspect I’m aware of is
that it is avoiding usage of
ExceptTto improve performance, which I have not investigated. We are currently aiming for stability here, but ideally any code written for haskell-ZIO could easily be transferred to using
Trio, or vice versa. If you see a difference, please raise an issue so we can document it or fix it.
The Scala-Haskell ZIO dictionary
The Scala ZIO type parameters and
largely reproduced in Haskell, though in some cases we can’t exactly
reproduce them. For instance,
IO is already taken in Haskell at
a very fundamental level. As well,
UIO has the same meaning as in
the Scala implementation, but it isn’t an alias, since it is an inner
monad of the
An apparent downsize of having
ZIO as distinct
(non-aliased) types is that one might feel inclined to provide APIs
for one or more of these when warranted. For this reason
UZIO a, and other aliases along with associated lift and unlift
functions are provided. These aliases have
Void in the expanded type,
and in some cases, it is more appropriate to use a universal quantifier,
e.g., when lifting into a type, we usually have some Error type in mind
Void (that’s one big reason why we’re using this library!),
so we’d prefer to have e.g.
uelift :: ∀ e a. UIO a -> EIO e a,
uelift :: UIO a -> UEIO a.