Creo que ya has agotado todas las posibilidades interesantes. Cualquier Monad m => m a -> m afunción que podamos definir se verá inevitablemente así:
e :: forall m a. Monad m => m a -> m a
e u = u >>= k
where
k :: a -> m a
k = _
En particular, si k = return, e = id. Para eno serlo id, kdebe usarlo u de una manera no trivial (por ejemplo, k = const uy k = flip fmap u . constequivaldrá a sus dos intentos). Sin embargo, en tal caso, los uefectos se duplicarán, lo eque conducirá a no ser un morfismo de mónada para una serie de opciones de mónada m. Siendo así, el único morfismo de la mónada es totalmente polimórfico en la mónada id.
Hagamos el argumento más explícito.
En aras de la claridad, cambiaré a la join/ return/ fmappresentación por un momento. Queremos implementar:
e :: forall m a. Monad m => m a -> m a
e u = _
¿Con qué podemos llenar el lado derecho? La elección más obvia es u. Por sí mismo, eso significa e = idque no parece interesante. Sin embargo, dado que también tenemos join, returny fmap, existe la opción de razonar inductivamente, con uel caso base. Digamos que tenemos algunos v :: m a, construidos utilizando los medios que tenemos a mano. Además de vsí mismo, tenemos las siguientes posibilidades:
join (return v), que es vy por lo tanto no nos dice nada nuevo;
join (fmap return v), que también lo es v; y
join (fmap (\x -> fmap (f x) w) v), para otro w :: m aconstruido de acuerdo con nuestras reglas, y algunos f :: a -> a -> a. (Agregar mcapas al tipo de f, como en a -> a -> m a, y joins extra para eliminarlas no llevaría a ninguna parte, ya que entonces tendríamos que mostrar la procedencia de esas capas, y las cosas finalmente se reducirían a los otros casos).
El único caso interesante es el # 3. En este punto, tomaré un atajo:
join (fmap (\x -> fmap (f x) w) v)
= v >>= \x -> fmap (f x) w
= f <$> v <*> w
Cualquier ulado no derecho, por lo tanto, puede expresarse en la forma f <$> v <*> w, con vy wsiendo una uo más iteraciones de este patrón, llegando eventualmente a us en las hojas. Sin embargo, las expresiones de aplicación de este tipo tienen una forma canónica, obtenida mediante el uso de las leyes de aplicación para reasociar todos los usos de (<*>)la izquierda, que en este caso debe verse así ...
c <$> u <*> ... <*> u
... con los puntos suspensivos representando cero o más ocurrencias adicionales de useparados por <*>, y cen a -> ... -> a -> afunción de la aridad apropiada. Como aes completamente polimórfico, cdebe, por paramétrica, ser una constfunción similar que elija uno de sus argumentos. Siendo así, cualquier expresión de este tipo puede reescribirse en términos de (<*)y (*>)...
u *> ... <* u
... con los puntos suspensivos representando cero o más ocurrencias adicionales de useparados por uno *>o por otro <*, no existiendo *>a la derecha de a <*.
Volviendo al inicio, todas las idimplementaciones no candidatas deben tener este aspecto:
e u = u *> ... <* u
También queremos eser un morfismo mónada. Como consecuencia, también debe ser un morfismo aplicativo. En particular:
-- (*>) = (>>) = \u v -> u >>= \_ -> v
e (u *> v) = e u *> e v
Es decir:
(u *> v) *> ... <* (u >* v) = (u *> ... <* u) *> (v *> ... <* v)
Ahora tenemos un camino claro hacia un contraejemplo. Si usamos las leyes aplicables para convertir ambos lados a la forma canónica, (todavía) terminaremos con usy s intercaladas ven el lado izquierdo, y con todas las vs después de todas las us en el lado derecho. Eso significa que la propiedad no se mantendrá para mónadas como IO, Stateo Writer, independientemente de cuántos (*>)y (<*)hay e, o exactamente qué valores son elegidos por las constfunciones similares en ambos lados. Una demostración rápida:
GHCi> e u = u *> u <* u -- Canonical form: const const <$> u <*> u <*> u
GHCi> e (print 1 *> print 2)
1
2
1
2
1
2
GHCi> e (print 1) *> e (print 2)
1
1
1
2
2
2
use duplicarán necesariamente a menos quee = id? (También podríamos escribire u = do _ <- u; _ <- u; _ <- u; uy combinar másuefectos). ¿Cómo podemos describir matemáticamente que "un valor monádicop :: m atiene múltiples efectos copiadosu :: m a? Y luego, ¿cómo podemos demostrar que los efectos duplicados (triplicados, etc.)unecesariamente conducen a violaciones de leyes de morfismo de mónadae u, es decir, usar alguna expresión del formulariou *> ... <* ucomo usted describió? Por qué no podemos encontrar alguna otra combinación inteligente y complicado defmap,returnyjoin, de modo que consigamos algo más? También es un buen movimiento considerar los morfismos aplicativos. Puede ser más fácil demostrar la propiedad análoga para los morfismos aplicativos que para los morfismos mónada. (¿Los únicos morfismos aplicativos que son aplicativamente naturales son los morfismos de identidad?)join _puede conducir a un noidresultado, y el # 3 es la única forma en que no conducirá aiduna regresión infinita. (2) EncendidoApplicative: informalmente, si su única flecha de Kleisli esreturn, no está utilizando la potencia extra queMonadtrae, por lo que también podría trabajarApplicative. (3) Sí, la propiedad análoga se cumple para los morfismos aplicativos. La parte de mi argumento que comienza con la forma canónica, que es autónoma, debería ser suficiente como prueba.