# Binds


Idiomatic Nix bind helpers: `bindAttrs`, `bindComp`, `bindFn`, plus the `optionalArg` sentinel.

## `bindAttrs`

_bindAttrs: sequence an attrset of effectful or send-able values; non-computation values become `send name value`, `optionalArg` probes via `has-handler` first._

```
bindAttrs : { <name> = Computation a | OptionalArg | Param; __sort? = [String] -> [String] } -> Computation { <name> = a }
```

Like a bind-chain but operates over named attrset of required-effects.

```nix
bind.attrs { foo = 99; bar = pure 22; baz = asks (env: env.baz); }
```

Values that are non-effects become send params: `send "foo" 99`.
Pass the `optionalArg` sentinel to mark a key as optional: bindAttrs
probes via `has-handler` first and omits the key when no handler is
installed (so a Nix function's default value can take over).

Result has same attr-keys with corresponding effect result.

See also: `bind.comp`, `bind.fn` for which this is the foundation.

# NOTE: Ordering of chained effects.

Since an attrSet has no order, this function chains effects in
same order as `builtins.attrNames` (alphabetical). If you need
an special order for computations that might be order senstive,
specify a `__sort = names => names` function.

## `bindComp`

_bindComp: turn an effectful function into an effect chain via `bindAttrs`; required args become required sends, optional args (with Nix defaults) probe via `has-handler`._

```
bindComp : { <name> = Computation a | Param } -> ({ <args> }: Computation b) -> Computation b
```

Turns a Nix effectful function into an effect chain via bindAttrs.

```nix
bindComp { bar = pure 22; } ({ foo, bar }: pure (foo * bar))
```

The function sees bar as the result of `pure 22` and `foo` as the
result of `send "foo" false` -- false comes directly from using
`lib.functionArgs f`, the handler can know if "foo" is optional in f.

Optional args (those with defaults in the Nix function) are probed
via has-handler before sending. If no handler exists, the arg is
skipped and the Nix default kicks in.

This works by using `bindAttrs` on the intersection of function args
and attrs.

## `bindFn`

_bindFn: like `bindComp` but for pure Nix functions; lifts the function's result into `pure` while still resolving its arguments through the effect system._

```
bindFn : { <name> = Computation a | Param } -> ({ <args> }: b) -> Computation b
```

Like bindComp but works on normal Nix functions and turns
its result into a pure-effect.

```nix
bindFn { bar = pure 22; } ({ foo, bar }: foo * bar)
```

## `optionalArg`

_optionalArg: sentinel for `bindAttrs`/`bindComp` optional effect arguments; absent handlers omit the attr so Nix defaults can apply._

```
optionalArg : OptionalArg
```

Sentinel value marking an attr as handler-conditional in `bindAttrs`.

