# One Line, Six Layers

_One compiled Effect Path line that edits an order, taken apart into the six layers it uses._

Here is a service method that changes the email address on an order. Its body is one expression, and it comes from a compiled, tested example, so it builds as shown.

```java
  static EitherPath<OrderError, Order> changeEmail(
      OrderRepository orders, UUID id, String newEmail) {
    return orders
        .find(id)
        .toEitherPath(OrderError.notFound(id))
        .map(order -> OrderFocus.customer().email().value().set(newEmail, order))
        .via(orders::save);
  }

```

`orders` is an `OrderRepository`. Its `find` returns a `MaybePath<Order>`, and its `save` returns an `EitherPath<OrderError, Order>`, refusing an order that has already shipped. `OrderFocus` is generated by `@GenerateFocus` on `Order`, one of the order-service records the [Optics chapter](../optics/ch_intro.md) introduces. Called for a new order, an unknown id and a shipped order, the method gives three answers:

```java
    Either<OrderError, Order> changed = changeEmail(orders, placed, "ada@example.org").run();
    // Right(Order[id=..., customer=Customer[name=Ada,
    //   email=EmailAddress[value=ada@example.org]], ...])
    Either<OrderError, Order> missing = changeEmail(orders, unknown, "ada@example.org").run();
    // Left(NotFound[orderId=...])
    Either<OrderError, Order> refused = changeEmail(orders, shipped, "ada@example.org").run();
    // Left(AlreadyShipped[orderId=...])
```

A missing order becomes a `NotFound` that carries its id. The new address goes in three records deep, and you write none of the copies: the lens rebuilds `Order`, `Customer` and `EmailAddress`. A save that refuses ends the chain with its own reason. Each failure is part of the return type, a value the caller handles, rather than an exception the signature never mentions.

~~~admonish info title="What You'll Learn"
- Name the layer of the library that each step of a Path expression uses, and the page that teaches it
- Choose `map` for a step that cannot fail, and `via` for a step that can
- Match each Path method to the type class operation over `Kind` that gives the same answer
~~~

~~~admonish example title="See Example Code"
**The code on this page is [OneLinerBook.java](https://github.com/higher-kinded-j/higher-kinded-j/blob/main/hkj-examples/src/main/java/org/higherkindedj/example/book/foundations/oneliner/OneLinerBook.java) and its [OneLinerBookTest.java](https://github.com/higher-kinded-j/higher-kinded-j/blob/main/hkj-examples/src/test/java/org/higherkindedj/example/book/foundations/oneliner/OneLinerBookTest.java)**: the page includes them, so the build compiles and runs them.
~~~

---

## Six layers in one expression

Each step of the line belongs to a different layer of the library, and the last column links the page that teaches it.

| Step | Layer | What it does here | Where to read more |
|---|---|---|---|
| `orders.find(id)` | An effect type | Returns a `MaybePath<Order>`: an order or nothing, as a value rather than a `null` | [Maybe](../monads/maybe_monad.md) |
| `.toEitherPath(OrderError.notFound(id))` | A natural transformation | Turns the `MaybePath` into an `EitherPath`, giving the empty case a reason and leaving the order untouched | [Natural Transformation](../functional/natural_transformation.md) |
| `OrderFocus.customer().email().value()` | An optic | A lens three records deep, whose `set` returns a new `Order` and leaves the old one as it was | [Optics](../optics/ch_intro.md) |
| `.map(order -> ...)` | Functor | Applies a function that cannot fail to the order inside, and does nothing on a `Left` | [Functor](../functional/functor.md) |
| `.via(orders::save)` | Monad | Runs a step that needs the edited order and can fail for a reason of its own | [Monad](../functional/monad.md) |
| The whole expression | The algebra | The same operations exist as type classes over `Kind<F, A>`, for one method that serves any container | [Two encodings, one algebra](#two-encodings-one-algebra) |

No step tests for failure. `EitherPath` carries a failure as a `Left`, and each later step passes the `Left` along without running. The interesting code is in the middle, where the domain logic lives.

---

## Two encodings, one algebra {#two-encodings-one-algebra}

Higher-Kinded-J offers `map`, `via` and their neighbours twice. On a Path, they are methods of a concrete type, as in the line. As type classes, they are methods of interfaces such as `Functor<F>` and `Monad<F>`, which work over `Kind<F, A>`: some container `F` holding an `A`, without saying which container. One method written that way serves any container:

| What you want | On a Path | As a type class over `Kind<F, A>` |
|---|---|---|
| Change the value inside | `path.map(f)` | `functor.map(f, fa)` |
| Combine two independent values | `path.zipWith(other, f)` | `applicative.map2(fa, fb, f)` |
| Run a step that needs the value and may fail | `path.via(f)` | `monad.flatMap(f, fa)` |
| Recover from an error | `path.recover(f)` | `monadError.handleError(fa, f)` |

`EitherPath` holds an `Either` and calls it directly: no `Kind` and no type class instance sit between your call and the `Either`. The type classes do a different job, one method for any container, as the [chapter introduction](foundations_intro.md)'s `totals` is. The two agree. Run through `Functor` and `Monad` over `Kind`, the email change gives the same `Right` or `Left` as the line for each of the three ids, and the page's test checks it.

`GenericPath.of(kind, monad)` joins the two encodings: it lifts any `Kind`, with its `Monad`, to the Path level. Most application code stays with Paths, and the "Which level am I working at?" tip in the [Foundations introduction](foundations_intro.md) says when to leave them.

---

## The same skeleton, different verbs

Once the skeleton is in place, a different change is a different middle step. Marking the order paid, or taking a discount off every line, leaves the rest of the line as it was:

```java
  static EitherPath<OrderError, Order> markPaid(OrderRepository orders, UUID id) {
    return orders
        .find(id)
        .toEitherPath(OrderError.notFound(id))
        .map(order -> OrderFocus.status().set(OrderStatus.PAID, order))
        .via(orders::save);
  }

  static EitherPath<OrderError, Order> discountEveryLine(
      OrderRepository orders, UUID id, UnaryOperator<BigDecimal> discount) {
    return orders
        .find(id)
        .toEitherPath(OrderError.notFound(id))
        .map(order -> OrderFocus.lines().price().modifyAll(discount, order))
        .via(orders::save);
  }

```

The discount uses a traversal, `OrderFocus.lines().price()`, which reaches every line's price at once, and `modifyAll` applies the discount to each one. Only the middle step changes, and each is a function from `Order` to `Order`, so one method that takes that function could serve all three.

~~~admonish note title="Why `OrderError.notFound(id)`, and not `new OrderError.NotFound(id)`?"
Mid-chain, `toEitherPath` has no target type to infer from, so it takes its error type from its argument. Given a `NotFound`, the whole chain's error type becomes `NotFound`, and the method no longer returns what it declares:

<!-- verify:rejects "NotFound,?>,B>" -->
```java
static EitherPath<OrderError, Order> changeEmail(
    OrderRepository orders, UUID id, String newEmail) {
  return orders
      .find(id)
      .toEitherPath(new OrderError.NotFound(id))
      .map(order -> OrderFocus.customer().email().value().set(newEmail, order))
      .via(orders::save);
}
```

The compiler rejects the `via`: `EitherPath<OrderError,Order> cannot be converted to Chainable<? extends EitherPath<? extends NotFound,?>,B>`. The chain is typed on `NotFound`, and `save` can fail with any `OrderError`. A factory typed as the sealed `OrderError` fixes the error type at the first step, so every later step fits. Naming the type once works too, as `.<OrderError>toEitherPath(new OrderError.NotFound(id))`, which the [Quickstart](../quickstart.md) uses. [Effect compiler errors](../effect/compiler_errors.md#a-chain-typed-on-one-variant) shows how to read the message, and the other places a chain takes its error type.
~~~

The Ship pages that follow take the type-class layers in order. They start beneath them, with how `Kind<F, A>` stands for a container, in [How the Encoding Works](core-concepts.md).

---

**Previous:** [Foundations](foundations_intro.md)
**Next:** [How the Encoding Works](core-concepts.md)
