zio-0.1.0.2: README.md
# haskell-zio
A [small](src/ZIO/Trans.hs) monad-transformer analogue to the
Scala [ZIO](https://github.com/zio/zio)
library (basically, [UIO](http://hackage.haskell.org/package/unexceptionalio) +
[Reader](hackage.haskell.org/package/transformers/docs/Control-Monad-Trans-Reader.html) +
[Either/ExceptT](hackage.haskell.org/package/mtl/docs/Control-Monad-Except.html)).
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](https://wiki.haskell.org/Error_vs._Exception)
part of the return-type of functions.
Note that this is meant to provide the same basic functionality of the `ZIO` monad.
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](http://hackage.haskell.org/package/unexceptionalio) 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
with `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](https://en.wikibooks.org/wiki/Java_Programming/Checked_Exceptions), where possible. See the [blog post](https://singpolyma.net/2018/05/error-handling-in-haskell/) (or [backup](docs/UIO.md)) for more details.
- [RIO](https://hackage.haskell.org/package/rio)
[integrates](hackage.haskell.org/package/rio/docs/src/RIO.Prelude.RIO.html#RIO) `ReaderT` with `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](https://github.com/snoyberg/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 `ExceptT` to 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
### Type Aliases
The Scala ZIO type parameters and
[aliases](https://zio.dev/docs/overview/overview_index#type-aliases) are
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 `ZIO` type.
An apparent downsize of having `UIO`, `EIO`, and `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 `UEIO e`,
`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
other than `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`,
not `uelift :: UIO a -> UEIO a`.
[//]: # (`nix-shell -p pandoc` then `pandoc TypesTable.md -o TypesTable.html`)
<table>
<colgroup>
<col style="width: 8%" />
<col style="width: 22%" />
<col style="width: 8%" />
<col style="width: 61%" />
</colgroup>
<thead>
<tr class="header">
<th>Haskell Type</th>
<th>Alias for</th>
<th>Scala Type</th>
<th>Notes</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>ZIO r e a</code></td>
<td></td>
<td><code>ZIO[R,E,A]</code></td>
<td></td>
</tr>
<tr class="even">
<td><code>UIO a</code></td>
<td></td>
<td><code>UIO[A]</code></td>
<td>This is a type alias in Scala but a concrete type in Haskell due to UIO being an inner monadic type.</td>
</tr>
<tr class="odd">
<td><code>EIO e a</code></td>
<td></td>
<td><code>IO[E, A]</code></td>
<td>This is a type alias in Scala but a concrete type in Haskell due to EIO being an inner monadic type.</td>
</tr>
<tr class="even">
<td><code>RIO r a</code></td>
<td><code>ZIO r SomeNonPseudoException a</code></td>
<td><code>RIO[R, A]</code></td>
<td>Same idea as in Scala. Not to be confused with the RIO library’s <code>RIO</code> monad, but they are isomorphic.</td>
</tr>
<tr class="odd">
<td><code>Task a</code></td>
<td><code>ZIO Void SomeNonPseudoException a</code></td>
<td><code>Task[A]</code></td>
<td></td>
</tr>
<tr class="even">
<td><code>UEIO a</code></td>
<td><code>EIO Void a</code></td>
<td><code>UIO[A]</code></td>
<td></td>
</tr>
<tr class="odd">
<td><code>URIO r a</code></td>
<td><code>ZIO r Void a</code></td>
<td><code>URIO[R, A]</code></td>
<td>Same idea as in Scala; a ZIO value isomorphic to a RIO value (can be projected to the RIO value).</td>
</tr>
<tr class="even">
<td><code>UZIO a</code></td>
<td><code>ZIO Void Void a</code></td>
<td><code>UIO[A]</code></td>
<td></td>
</tr>
</tbody>
</table>