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 .