monadas functores design-patterns haskell functional-programming monads

design-patterns - functores y monadas haskell



¿Cuál es el nombre de este patrón de programación funcional tipo mónada? (1)

Bueno, en cierto sentido está estrechamente relacionado con las mónadas, solo que es incompatible con la clase de tipo Monad . En particular, podemos observar los siguientes paralelos:

  • Los monoides tienen una operación asociativa con identidad definida en valores de un tipo consistente: mappend :: a -> a -> a mempty :: a .

  • Las mónadas tienen una operación asociativa con identidad definida en los constructores de tipos , por ejemplo: join :: m (ma) -> ma y return :: a -> ma .

  • Las funciones - en realidad, las flechas en una categoría - tienen una operación e identidad asociativa, pero la operación asociativa está indexada por los objetos de la categoría , que aquí significa "tipos": (.) :: arr bc -> arr ab -> arr ac y id :: arr aa .

... entonces, ¿cuál sería una mónada cuya join está indexada por tipos? Hm

Algunas referencias que podrían encontrar interesantes, explorando conceptos relacionados:

post scriptum - Has dicho esto en un comentario sobre la pregunta:

Tienes razón. De hecho, quiero arreglarlo para que sea más parecido a una mónada, aunque en realidad no estoy "usando" mónadas. Yo lo edito Aunque tendría más o menos la misma pregunta sobre los aplicativos.

En realidad, ¡limitar las cosas a los cambios Applicative importa significativamente! La diferencia entre a -> Marked pb y Marked p (a -> b) es que, en el primero, las propiedades de la estructura Marked p pueden depender del parámetro a; mientras que en este último, el marcado es independiente de los argumentos de la función. La independencia significa que los dos pueden tratarse por separado, lo que simplifica las cosas considerablemente; teniendo en cuenta que cualquier valor de tipo a es isomorfo a una función de tipo () -> a , probablemente pueda convertirlo en una versión de Arrow de dos niveles de manera directa.

Por otro lado, involucrar a Monad implica cierto grado de intercalación entre las funciones y el contexto de marcado, lo que complica las cosas por razones similares a las que se discutieron en las respuestas a esta pregunta .

Ocasionalmente he encontrado un patrón en el código que se parece a una mónada pero no mantiene un tipo consistente en >>= .

Aquí está el ejemplo más simple que podría encontrar:

(Primero algunos booleanos de nivel de tipo:

data TyT = TyT data TyF = TyF class TyOr a b c | a b -> c instance TyOr TyF TyF TyF -- rest similarly

)

Ahora aquí está nuestro constructor de tipo "mónada":

data Marked p a = Marked a deriving (Show)

Para una p dada, Marked p es un * -> * que actúa como m en una mónada, pero diferente, como ocurre a continuación, cuando definimos "vinculación":

(>>%) :: (TyOr p q r) => Marked p a -> (a -> Marked q b) -> Marked r b (Marked x) >>% f = Marked y where Marked y = f x

Lo que es diferente aquí es que el resultado de >>% tiene un constructor de tipo diferente a los argumentos. Aparte de eso, es básicamente una mónada.

Podríamos usarlo así:

a :: Marked TyF Int a = Marked 5 f :: Int -> Marked TyT Int f x = Marked (x + 1) ghci> a >>% f Marked 6 ghci> :t a >>% f a >>% f :: Marked TyT Int

(Esto se inspiró en la observación de outis de que Python "con" no puede ser una mónada porque cambia el tipo , pero también lo he visto de otra manera (más simple)).