¿Buenos ejemplos de No es un Functor/Functor/Aplicativo/Mónada?

Resuelto Rotsor asked hace 13 años • 5 respuestas

Mientras le explico a alguien qué es una clase de tipo X, me cuesta encontrar buenos ejemplos de estructuras de datos que sean exactamente X.

Entonces, solicito ejemplos para:

  • Un constructor de tipos que no es un Functor.
  • Un constructor de tipos que es un Functor, pero no un Aplicativo.
  • Un constructor de tipos que es un aplicativo, pero no una mónada.
  • Un constructor de tipos que es una mónada.

Creo que hay muchos ejemplos de Monad en todas partes, pero un buen ejemplo de Monad con alguna relación con ejemplos anteriores podría completar el cuadro.

Busco ejemplos que sean similares entre sí, diferenciándose sólo en aspectos importantes para pertenecer a la clase de tipo particular.

Si uno pudiera lograr encontrar un ejemplo de Arrow en algún lugar de esta jerarquía (¿está entre Applicative y Monad?), ¡eso también sería genial!

Rotsor avatar Aug 28 '11 17:08 Rotsor
Aceptado

Un constructor de tipos que no es un Functor:

newtype T a = T (a -> Int)

Puedes crear un funtor contravariante a partir de él, pero no un funtor (covariante). Intenta escribir fmapy fracasarás. Tenga en cuenta que la versión del functor contravariante está invertida:

fmap      :: Functor f       => (a -> b) -> f a -> f b
contramap :: Contravariant f => (a -> b) -> f b -> f a

Un constructor de tipos que es un functor, pero no aplicativo:

No tengo un buen ejemplo. Lo hay Const, pero lo ideal sería que fuera un monoide concreto y no se me ocurre ninguno. Todos los tipos son básicamente numéricos, enumeraciones, productos, sumas o funciones, en definitiva. Puede ver a continuación que Pigworker y yo no estamos de acuerdo sobre si Data.Voides un Monoid;

instance Monoid Data.Void where
    mempty = undefined
    mappend _ _ = undefined
    mconcat _ = undefined

Dado que _|_es un valor legal en Haskell y, de hecho, el único valor legal de Data.Void, cumple con las reglas de Monoid. No estoy seguro de qué unsafeCoercetiene que ver con esto, porque ya no se garantiza que su programa no viole la semántica de Haskell tan pronto como utilice cualquier unsafefunción.

Consulte Haskell Wiki para obtener un artículo sobre funciones inferiores ( enlace ) o inseguras ( enlace ).

Me pregunto si es posible crear un constructor de tipos de este tipo utilizando un sistema de tipos más rico, como Agda o Haskell con varias extensiones.

Un constructor de tipos que es un aplicativo, pero no una mónada:

newtype T a = T {multidimensional array of a}

Puedes crear un aplicativo con algo como:

mkarray [(+10), (+100), id] <*> mkarray [1, 2]
  == mkarray [[11, 101, 1], [12, 102, 2]]

Pero si la convierte en una mónada, podría producirse una discrepancia de dimensiones. Sospecho que ejemplos como este son raros en la práctica.

Un constructor de tipos que es una mónada:

[]

Acerca de las flechas:

Preguntar dónde se encuentra una flecha en esta jerarquía es como preguntar qué tipo de forma es "roja". Tenga en cuenta la discrepancia de tipos:

Functor :: * -> *
Applicative :: * -> *
Monad :: * -> *

pero,

Arrow :: * -> * -> *
Dietrich Epp avatar Aug 28 '2011 11:08 Dietrich Epp

Puede que mi estilo se vea limitado por mi teléfono, pero ahí va.

newtype Not x = Kill {kill :: x -> Void}

no puede ser un Funtor. Si lo fuera, tendríamos

kill (fmap (const ()) (Kill id)) () :: Void

y la Luna estaría hecha de queso verde.

Mientras tanto

newtype Dead x = Oops {oops :: Void}

es un funtor

instance Functor Dead where
  fmap f (Oops corpse) = Oops corpse

pero no puede ser aplicable, o tendríamos

oops (pure ()) :: Void

y el Verde estaría hecho de queso Luna (lo que en realidad puede suceder, pero sólo más tarde en la noche).

(Nota adicional: Void, ya que Data.Voides un tipo de datos vacío. Si intenta usarlo undefinedpara demostrar que es un Monoide, lo usaré unsafeCoercepara demostrar que no lo es).

alegremente,

newtype Boo x = Boo {boo :: Bool}

es aplicable de muchas maneras, por ejemplo, como diría Dijkstra,

instance Applicative Boo where
  pure _ = Boo True
  Boo b1 <*> Boo b2 = Boo (b1 == b2)

pero no puede ser una mónada. Para ver por qué no, observe que el retorno debe ser constante Boo Trueo Boo False, y por lo tanto que

join . return == id

No es posible que aguante.

Oh sí, casi lo olvido

newtype Thud x = The {only :: ()}

es una mónada. Enrolla el tuyo.

Avión para coger...

pigworker avatar Aug 28 '2011 12:08 pigworker

Creo que las otras respuestas omitieron algunos ejemplos simples y comunes:

Un constructor de tipos que es un Functor pero no un Aplicativo. Un ejemplo simple es un par:

instance Functor ((,) r) where
    fmap f (x,y) = (x, f y)

Pero no hay manera de definir su Applicativeinstancia sin imponer restricciones adicionales r. En particular, no hay forma de definir pure :: a -> (r, a)un arbitrario r.

Un constructor de tipos que es un aplicativo, pero no una mónada. Un ejemplo bien conocido es ZipList . (Es un newtypesistema que envuelve listas y Applicativeles proporciona una instancia diferente).

fmapse define de la forma habitual. Pero purey <*>se definen como

pure x                    = ZipList (repeat x)
ZipList fs <*> ZipList xs = ZipList (zipWith id fs xs)

entonces purecrea una lista infinita repitiendo el valor dado y <*>comprime una lista de funciones con una lista de valores; aplica la i -ésima función al i -ésimo elemento. (El estándar <*>produce []todas las combinaciones posibles para aplicar la i -ésima función al j -ésimo elemento). Pero no existe una forma sensata de definir una mónada (consulte esta publicación ).


¿Cómo encajan las flechas en la jerarquía funtor/aplicativo/mónada? Ver Los modismos son ajenos, las flechas son meticulosas, las mónadas son promiscuas por Sam Lindley, Philip Wadler, Jeremy Yallop. MSFP 2008. (Lo llaman modismos de funtores aplicativos ). El resumen:

Revisamos la conexión entre tres nociones de computación: las mónadas de Moggi, las flechas de Hughes y los modismos de McBride y Paterson (también llamados functores aplicativos). Mostramos que los modismos son equivalentes a flechas que satisfacen el isomorfismo de tipo A ~> B = 1 ~> (A -> B) y que las mónadas son equivalentes a flechas que satisfacen el isomorfismo de tipo A ~> B = A -> (1 ~ >B). Además, los modismos se incrustan en flechas y las flechas se incrustan en mónadas.

Petr avatar Aug 27 '2012 06:08 Petr

Un buen ejemplo de un constructor de tipos que no es un funtor es Set: No se puede implementar fmap :: (a -> b) -> f a -> f b, porque sin una restricción adicional Ord bno se puede construir f b.

Landei avatar Aug 29 '2011 06:08 Landei