I've been trying to grasp IO monad for a while now and it makes sense. If I'm not mistaken, the goal is to split the description of the side effect and the actual execution. As in the example below, Scala has a way to get an environment variable which is not referentially transparent. Two questions arose.
Question 1: Is this one referentially transparent
Question 2: How to properly (unit/property-based) test this? It's not possible to check for equality because it will check for memory reference and it's not possible to check the inner function because function comparison is not possible if I'm not mistaken. But, I don't want to run the actual side effect in my unit test. Also, is this a design mistake or a misuse of the IO monad?
case class EnvironmentVariableNotFoundException(message: String) extends Exception(message)
object Env {
def get(envKey: String): IO[Try[String]] = IO.unit.flatMap((_) => IO.pure(tryGetEnv(envKey)))
private[this] def tryGetEnv(envKey: String): Try[String] =
Try(System.getenv(envKey))
.flatMap(
(x) =>
if (x == null) Failure(EnvironmentVariableNotFoundException(s"$envKey environment variable does not exist"))
else Success(x)
)
}