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 .