para pagina online oficial mac instalar descargar compiler como haskell ghc

haskell - pagina - ¿Por qué(>>) no está definido como(*>)?



haskell pagina oficial (2)

De acuerdo con un comentario en el código fuente , es para evitar que las personas creen accidentalmente un enlace recursivo si anulan *> as >> en su instancia de Applicative .

(>>) :: forall a b. m a -> m b -> m b m >> k = m >>= /_ -> k -- See Note [Recursive bindings for Applicative/Monad]

La nota dice:

Nota: Enlaces recursivos para Aplicativo / Mónada.

La propuesta original del Aplicativo / Mónada indicaba que después de la implementación, la implementación designada de (>>) se convertiría en

(>>) :: forall a b. m a -> m b -> m b (>>) = (*>)

por defecto. Podría estar inclinado a cambiar esto para reflejar la propuesta establecida, ¡pero realmente no debería! ¿Por qué? Debido a que las personas tienden a definir tales instancias al revés: en particular, es perfectamente legítimo definir una instancia de Applicative (*>) en términos de (>>) , lo que llevaría a un bucle infinito para la implementación predeterminada de Monad ! Y la gente hace esto en la naturaleza.

Esto se convirtió en un error desagradable que fue difícil de rastrear, y en lugar de eliminarlo en todas partes en sentido ascendente, es más fácil mantener el valor predeterminado original.

GHC implementa actualmente >> como

(>>) :: m a -> m b -> m b m >> k = m >>= /_ -> k

¿Por qué no hacer lo siguiente?

(>>) :: m a -> m b -> m b m >> k = m *> k

En este momento, estoy pensando que >>= hace algo *> no.

Pero todo funciona de forma gramatical (como en el tipo), por lo que es muy difícil razonar por qué no funcionaría. Tal vez la instancia de la mónada hace algún cálculo que la instancia aplicativa no lo hace, pero creo que esto rompería la semántica del tipo.

Actualización solo puedo elegir una respuesta SO como aceptada, pero la respuesta de dfeuer es muy perspicaz (especialmente, para las personas que, como yo, tienen relativamente poca experiencia en Haskell).


La respuesta de 4castle es correcta, por supuesto, pero hay otra cosa que considerar. No todas las instancias de liftA2 = liftM2 admiten una instancia de Applicative más eficiente que liftA2 = liftM2 . Es decir,

liftA2 f xs ys = xs >>= /x -> ys >>= /y -> pure (f x y)

Usando el valor predeterminado (*>) = liftA2 (flip const) da

xs *> ys = xs >>= / _ -> ys >>= /y -> pure y

Por otro lado, la definición por defecto de (>>) da

xs >> ys = xs >>= / _ -> ys

Como puede ver, esto usa solo un enlace, mientras que el otro usa dos. Por una ley de identidad de la mónada, son equivalentes, pero el compilador no conoce las leyes de la mónada. Por lo tanto, el enfoque que sugiera probablemente hará que el optimizador trabaje más, e incluso puede evitar que produzca el mejor código en algunos casos.