# Solutions to "Scala with Cats": Chapter 4

April 4, 2023

These are my solutions to the exercises of chapter 4 of Scala with Cats.

## Exercise 4.1.2: Getting Func-y

We have `pure` and `flatMap` to define `map`. We want to start from an `F[A]` and get to an `F[B]` from a function `A => B`. As such, we want to call `flatMap` over the value. We can’t use `func` directly, though. However, we can produce a function that would lift our value to an `F` using `pure` (```a => pure(func(a))```):

## Exercise 4.3.1: Monadic Secret Identities

`pure`, `map` and `flatMap` for `Id` can be implemented as follows:

Since `Id[A]` is just a type alias for `A`, we can notice that we avoid all boxing in the implementations and, due to that fact, `flatMap` and `map` are identical.

## Exercise 4.4.5: What is Best?

The answer depends on what we are looking for in specific instances, but some things that the previous examples for error handling don’t cover are:

• We can’t accumulate errors. The proposed examples all fail fast.
• We can’t tell exactly where the error was raised.
• It’s not easy to do error recovery.

## Exercise 4.5.4: Abstracting

A possible implementation for `validateAdult` is the following:

If `age` is greater than or equal to 18, we summon an `Applicative` for `F` (which we must have in scope due to `MonadError`) and lift the `age` to `F`. If `age` is less than 18, we use the `MonadError` instance we have in scope to lift an `IllegalArgumentException` to `F`.

## Exercise 4.6.5: Safer Folding using Eval

One way to make the naive implementation of `foldRight` stack safe using `Eval` is the following:

We defer the call to the recursive step and then map over it to apply `fn`, all within the context of `Eval`.

## Exercise 4.7.3: Show Your Working

A possible rewrite of `factorial` so that it captures the log messages in a `Writer` is the following:

We can show that this allows us to reliably separate the logs for concurrent computations because we have the logs for each instance captured in each `Writer` instance:

## Exercise 4.8.3: Hacking on Readers

To create a type alias for a `Reader` that consumes a `Db` we want to fix the first type parameter of `Reader` to `Db`, while still leaving the result type as a type parameter:

The `findUsername` and `checkPassword` functions can be implemented as follows:

The `checkLogin` method can be implemented as follows:

We are making use of the `findUsername` and `checkPassword` methods. There are two scenarios in which `checkLogin` can return a `false` for a given `Db`: when the username doesn’t exist and when the password doesn’t match.

## Exercise 4.9.3: Post-Order Calculator

A possible implementation of `evalOne` with no proper error handling is the following:

We’re not told which operands to support, so I assumed at least `+`, `*`, `-` and `/`.

For the `evalAll` implementation, we’re not told what to do in case the input is empty. I assumed it would be OK to just have an exception thrown (since that was the case before), and relied on `reduce` over the `evalOne` calls:

The `evalInput` method can rely on a call to `evalAll` after splitting the input by whitespaces:

## Exercise 4.10.1: Branching out Further with Monads

One implementation of `Monad` for `Tree` is the following:

However, `tailRecM` isn’t tail-recursive. We can make it tail-recursive by making the recursion explicit in the heap. In this case, we’re using two mutable stacks: one of open nodes to visit and one of already visited nodes. On that stack, we use `None` to signal a non-leaf node and a `Some` to signal a leaf node.