a little pointless work

This commit is contained in:
Alexander 2025-07-01 00:34:25 -04:00
parent 120aaee0e3
commit e5d436e1cd

View file

@ -47,11 +47,16 @@ Each of these functors accepts an instance of a less general structure and uses
The more involved implementation in `ApplicativeOfMonad` is where we get some options in terms of implementation and also, not unrelatedly, where our problems arise. Because it turns out that there are multiple ways to implement the derivation functor--- also multiple ways to implement a particular monad or applicative--- it becomes hard to predict whether a derived implementation is the expected one without resorting to _ad hoc_ testing, testing that rather defeats the point of "gratis"[^low-effort]. The `apply` function, shown above, is derived from `bind` and `return` by threading `x` and `f` into the context through bind (as `y` and `g`, respectively), thus "stripping off" the context in the body of the lambda, then applying `g` to `y` to obtain a fresh `'b`, and finally passing that `'b` to `M.return`, thus producing a `'b M.t`, which of course is also an `'a t`, since `type 'a t = 'a M.t`[^with-type].
To explore concretely how deriving instances can go wrong, consider the following `BarMonad.
To explore concretely how deriving instances can go wrong, consider the following `EitherMonad`.
```ocaml
module BarMonad : Monad with type 'a t = 'a bar = struct
...
type ('a, 'b) either = A of 'a | B of 'b
module EitherMonad (T : sig type t end) : Monad with type 'a t = ('a, T.t) either = struct
return x = [x]
let rec bind (f : 'a -> 'b list) : 'a list -> 'b list = function
| [] -> []
| x :: xs -> f x @ bind f xs
end
```