haskell ghc monoids

haskell - ¿Por qué GHC no puede derivar instancias para Monoid?



monoids (2)

GHC tiene algunas DeriveFunctor idioma, como DeriveFunctor , DeriveFunctor , etc., que permiten la generación del compilador de instancias derivadas para clases de tipo distintas a las permitidas en Haskell 98. Esto tiene sentido especialmente para algo como Functor , donde las leyes de esa clase dictan una Obviamente, "natural" deriva instancia.

Entonces, ¿por qué no para Monoid ? Parece que para cualquier tipo de datos con un único constructor de datos:

data T = MkT a b c ...

uno podría producir mecánicamente una instancia de Monoid (disculpe el pseudocódigo):

instance (Monoid a, Monoid b, Monoid c, ...) => Monoid T where mempty = MkT mempty mempty mempty ... mappend (MkT a1 b1 c1 ...) (MkT a2 b2 c2 ...) = MkT (mappend a1 a2) (mappend b1 b2) (mappend c1 c2) ...

Soy consciente de que el paquete derive proporciona esto , pero mi pregunta específicamente es si hay una razón por la cual GHC no lo hace.


En realidad, es una decisión arbitraria no poder obtener Monoid , pero los monoids también son muy generales, por lo que generalmente hay muchas formas de hacer que un monoide sea un tipo. Aquí hay un ejemplo:

data T = A | B | C deriving (Eq, Ord, Enum) type Mon a = (a, a -> a -> a) m1, m2, m3, m4 :: Mon T m1 = (A, max) m2 = (C, min) m3 = (A, / x y -> toEnum $ (fromEnum x + fromEnum y) `rem` 3) m4 = (B, f4) f4 A _ = A f4 B x = x f4 C _ = C

Esto muestra cuatro formas razonables de convertir T un monoide (con Mon contiene la unidad y la operación binaria). El primero es el monoide de tomar el máximo, el segundo el monoide de tomar el mínimo, el tercero el monoide de la aritmética de módulo 3 y el cuarto es el monoide utilizado para el tipo de Ordering . Nada realmente se destaca como la forma natural.


Podrías pedir lo mismo para Num y algunas otras clases. Sería intrascendente: todas las demás derivaciones estándar funcionan para tipos de datos con múltiples constructores.

Como reemplazo, puede usar newtype derivando newtype T = MkT (a,b,c) deriving Monoid .

Extensión similar: puede hacer que el tipo de datos vacío sea una instancia de casi todas las clases de tipos.

La cláusula deriving siempre fue una parte ad hoc e inconveniente de Haskell, ya que solo funcionaba para clases predefinidas. Agregar aún más extensiones ad-hoc complicaría el lenguaje. En cambio, GHC recientemente ha recibido soporte para la obtención de genéricos .