nrktkt / ioh   0.1.0

The Unlicense GitHub

() => Future(println("oh"))

Scala versions: 2.13

IOh

Maven Central

() => Future(println("oh"))

Add referential transparency and laziness with Future. Making it safe(r) to use Future with tagless-final.

Say we want to adopt some cats, we just need to name them.

def adoptCats[F[_]: Monad](generateName: F[String]): F[String] = 
  for {
    cat1 <- generateName
    cat2 <- generateName
  } yield s"enjoy your new cats, $cat1 and $cat2"

Using Future it's going to be confusing having two cats with the same name.

adoptCats(Future(pickACatNameAtRandom()))
  .onSuccess(println) 
// enjoy your new cats, fluffy and fluffy

IOh is just an alias for () => Future, so just add the lambda to our previous code and we're good to go.

import io.github.kag0.ioh._
adoptCats(() => Future(pickACatNameAtRandom()))
  .apply()
  .onSuccess(println) 
// enjoy your new cats, fluffy and snowball

Adds instances for Effect, and Parallel which provides

  • Functor
  • Applicative
  • Monad
  • MonadError
  • Defer
  • Sync
  • Async
  • etc

Why is this useful?

Most errors around the lack of referential transparency in Future are not coming from developers using Future directly in their code. Future's semantics are generally understood, and code is structured around it. The issues arise when tagless-final comes into the picture, and the developers working with the tagless-final code are assuming their Fis safe. Many libraries in the Scala ecosystem use tagless-final so that their users can decide which side effect or async monad they want to use (this is a good thing).

IOh exists for the codebases which are using Future and interfacing with tagless-final code, to protect them from violating the assumptions made by the developers working on the tagless-final code.
Lifting a Future to an IOh is as simple as wrapping that Future's creation in a Function0.