opciones hacer funciones ejemplos composicion como haskell monads fold function-composition

hacer - haskell ejemplos



Plegado, composición de funciones, mónadas y pereza, ¿oh mi? (2)

Estoy confundido. Puedo escribir esto

import Control.Monad main = print $ head $ (foldr (.) id [f, g]) [3] where f = (1:) g = undefined

y la salida es 1 . Eso tiene sentido, porque se reduce a:

main = print $ head $ ((1:) . undefined . id) [3] main = print $ head $ (1:) ((undefined . id) [3]) main = print $ head $ 1 : ((undefined . id) [3]) main = print $ 1

Pero si utilizo una técnica monádica vagamente similar, no funciona igual:

import Control.Monad main = print $ (foldr (<=<) return [f, g]) 3 where f = const Nothing g = undefined

Esto golpea prelude.Undefined . Lo cual es extraño, porque esperaría que se redujera:

main = print $ ((const Nothing) <=< undefined <=< return) 3 main = print $ return 3 >>= undefined >>= (/_ -> Nothing) main = print $ Nothing -- nope! instead, undefined makes this blow up

Sin embargo, cambiando el orden de la composición:

import Control.Monad main = print $ (foldr (>=>) return [f, g]) 3 where f = const Nothing g = undefined

cumple el corto circuito esperado y no produce Nothing .

main = print $ (const Nothing >=> undefined >=> return) 3 main = print $ (const Nothing 3) >>= undefined >>= return main = print $ Nothing >>= undefined >>= return main = print $ Nothing

Supongo que comparar los dos enfoques podría haber sido comparar manzanas y naranjas, pero ¿puedes explicar la diferencia? Pensé que f <=< g era el análogo monádico de f . g f . g , pero aparentemente no son tan análogos como pensaba. ¿Puedes explicar porque?


Depende de con qué mónada esté trabajando y de cómo esté definido su operador (>>=) .

En el caso de Maybe , (>>=) es estricto en su primer argumento, como explicó Daniel Fischer.

Aquí hay algunos resultados para un puñado de otras mónadas.

> :set -XNoMonomorphismRestriction > let foo = (const (return 42) <=< undefined <=< return) 3 > :t foo foo :: (Num t, Monad m) => m t

Identidad: perezosa.

> Control.Monad.Identity.runIdentity foo 42

IO: Estricto.

> foo :: IO Integer *** Exception: Prelude.undefined

Lector: perezoso.

> Control.Monad.Reader.runReader foo "bar" 42

Escritor: Tiene tanto una variante perezosa como una estricta.

> Control.Monad.Writer.runWriter foo (42,()) > Control.Monad.Writer.Strict.runWriter foo *** Exception: Prelude.undefined

Estado: Tiene también una versión tanto estricta como perezosa.

> Control.Monad.State.runState foo "bar" (42,"*** Exception: Prelude.undefined > Control.Monad.State.Strict.runState foo "bar" *** Exception: Prelude.undefined

Cont: Estricto.

> Control.Monad.Cont.runCont foo id *** Exception: Prelude.undefined


El vínculo para Maybe es estricto en el primer argumento.

Just v >>= f = f v Nothing >>= f = Nothing

Así que cuando intentas

Just v >>= undefined >>= /_ -> Nothing

tu golpeas

undefined v >>= /_ -> Nothing

y la implementación debe averiguar si undefined v es Nothing o Just something para ver qué ecuación de (>>=) usar.

Por otra parte,

Nothing >>= undefined

determina el resultado sin mirar el segundo argumento de (>>=) .