### Brand Inference

The HKT encoding above provides a **forward mapping** from brands to concrete types
(`OptionBrand` -> `Option<A>`), but the compiler has no way to go backwards: given
`Option<A>`, it cannot determine that `OptionBrand` is the right brand. This means
every free function call would require a turbofish annotation:

```rust
use fp_library::{brands::*, functions::explicit::*};

// Without brand inference, the brand must be specified explicitly
let y = map::<OptionBrand, _, _, _, _>(|x: i32| x + 1, Some(5));
```

Brand inference adds the **reverse mapping** (concrete type -> brand), letting the
compiler infer the brand automatically:

```rust
use fp_library::functions::*;

// Brand inferred from Option<i32>
let y = map(|x: i32| x + 1, Some(5));
assert_eq!(y, Some(6));
```

#### How it works

For each `Kind_{hash}` trait generated by `trait_kind!`, a corresponding
`InferableBrand_{hash}` trait is also generated:

```rust,ignore
trait_kind!(type Of<'a, A: 'a>: 'a;)

// Generates both:

// Forward: Brand -> Type
trait Kind_cdc7cd43dac7585f {
    type Of<'a, A: 'a>: 'a;
}

// Reverse: Type -> Brand
trait InferableBrand_cdc7cd43dac7585f {
    type Brand: Kind_cdc7cd43dac7585f;
}

// Blanket ref impl
impl<T: InferableBrand_cdc7cd43dac7585f + ?Sized>
    InferableBrand_cdc7cd43dac7585f for &T
{
    type Brand = T::Brand;
}
```

When `impl_kind!` defines a brand, it generates both mappings:

```rust,ignore
impl_kind! {
    for OptionBrand {
        type Of<'a, A: 'a>: 'a = Option<A>;
    }
}

// Generates both:

// Forward
impl Kind_cdc7... for OptionBrand {
    type Of<'a, A: 'a>: 'a = Option<A>;
}

// Reverse
impl<A> InferableBrand_cdc7... for Option<A> {
    type Brand = OptionBrand;
}
```

The inference-based `map` function uses `InferableBrand` to resolve the brand
from the container type `FA`:

```rust,ignore
pub fn map<FA, A, B, Marker>(
    f: impl FunctorDispatch<FA::Brand, A, B, FA, Marker>,
    fa: FA,
) -> ...
where
    FA: InferableBrand_cdc7...,
{
    f.dispatch(fa)
}
```

When the caller writes `map(|x| x + 1, Some(5))`, the compiler:

1. Infers `FA = Option<i32>` from the second argument.
2. Finds `impl InferableBrand for Option<A>` and resolves `Brand = OptionBrand`.
3. Uses `OptionBrand` to select the correct `FunctorDispatch` impl.

The blanket `impl InferableBrand for &T` enables the same inference for borrowed
containers: `map(|x: &i32| *x + 1, &Some(5))` infers `FA = &Option<i32>`,
delegates to `Option<i32>`'s impl, and resolves `Brand = OptionBrand`.

#### Multi-brand types

Some types are reachable through multiple brands at a given arity.
`Result<A, E>` has four arity-1 brands (`ResultErrAppliedBrand<E>`,
`ResultOkAppliedBrand<A>`, and two bifunctor-derived brands), making
arity-1 inference ambiguous. These types do not implement the arity-1
`InferableBrand` trait, so `map(f, Ok(5))` produces a compile error with
an actionable diagnostic:

```text
error: `Result<i32, String>` does not have a unique brand and cannot use brand inference
  = note: use the `explicit::` variant with a turbofish to specify the brand manually
```

However, at arity 2, `Result` has exactly one brand (`ResultBrand`), so
`bimap((f, g), Ok(5))` infers the brand successfully. The ambiguity is
arity-specific, not type-specific.

#### The `#[no_inferable_brand]` attribute

`impl_kind!` generates `InferableBrand` impls by default. For multi-brand
types, add `#[no_inferable_brand]` to suppress generation:

```rust,ignore
impl_kind! {
    #[no_inferable_brand]
    impl<E> for ResultErrAppliedBrand<E> {
        type Of<'a, A: 'a>: 'a = Result<A, E>;
    }
}
```

Generation is also automatically skipped when the target type is a projection
(contains `Apply!` or `::`) or when multiple associated types are defined.

#### Relationship to Val/Ref dispatch

Brand inference determines _which type constructor_ to use; [Val/Ref dispatch](./dispatch.md)
determines _which trait method_ (by-value or by-reference) to call. The two
systems compose through the shared `FA` type parameter: brand inference resolves
`FA` to a brand, while dispatch resolves `FA`'s ownership to a `Val` or `Ref`
marker. Together they enable fully inferred calls like `map(|x: i32| x + 1, Some(5))`
with no turbofish and no explicit val/ref selection.
