(+)
y (++)
son solo especializaciones de mappend
; estoy en lo cierto? ¿Por qué son necesarios? Esta es una duplicación inútil ya que Haskell tiene estas potentes clases de tipos e inferencias de tipo. Digamos que eliminamos (+)
y (++)
y cambiamos el nombre a mappend
(+)
por comodidad visual y aumento de tipeo. codificación sería más intuitiva, más corto y más comprensible para los principiantes:Haskell: funciones duplicadas (+) y (++), mappend
--old and new
1 + 2
--result
3
--old
"Hello" ++ " " ++ "World"
--new
"Hello" + " " + "World"
--result
"Hello World"
--old
Just [1, 2, 3] `mappend` Just [4..6]
--new
Just [1, 2, 3] + Just [4..6]
--result
Just [1, 2, 3, 4, 5, 6]
(Se me hace soñar.). Tres, y tal vez más, funciones para la misma cosa no son buenas para un lenguaje bello que insiste en la abstracción y cosas como Haskell. También vi el mismo tipo de repeticiones con mónadas: fmap
es el mismo, o casi, como map
, (.)
, liftM
, mapM
, forM
, ... Sé que hay razones para fmap
Histórica, pero ¿qué pasa monoides? ¿El comité de Haskell está planeando algo sobre esto? Sería romper algunos códigos, pero escuché, aunque no estoy seguro, hay una versión entrante que tendrá grandes cambios, que es una gran ocasión. Es una lástima ... Al menos, ¿es asequible un tenedor?
EDITAR En las respuestas que he leído, no es el hecho de que para los números, ya sea (*)
o (+)
podrían caber en mappend
. De hecho, creo que (*)
debería ser parte de Monoid
! Mire:
Actualmente, olvidando las funciones mempty
y mconcat
, solo tenemos mappend
.
class Monoid m where
mappend :: m -> m -> m
Pero podríamos hacer eso:
class Monoid m where
mappend :: m -> m -> m
mmultiply :: m -> m -> m
Sería (tal vez, no tienen suficiente, aunque en ello todavía) se comportan de la siguiente manera:
3 * 3
mempty + 3 + 3 + 3
0 + 3 + 3 + 3
9
Just 3 * Just 4
Just (3 * 4)
Just (3 + 3 + 3 +3)
Just 12
[1, 2, 3] * [10, 20, 30]
[1 * 10, 2 * 10, 3 * 10, ...]
[10, 20, 30, 20, 40, 60, ...]
realidad 'mmultiply' simplemente se definiría solo en términos de 'mappend', por lo que para casos de Monoid
no hay necesidad de redefinirlo. Entonces Monoid
está más cerca de las matemáticas; ¡quizás también podríamos agregar (-)
y (/)
a la clase! Si esto funciona, creo que resolvería el caso de Sum
y Product
, así como la duplicación de funciones: mappend
se convierte en (+)
y el nuevo mmultiply
es solo (*)
. Básicamente sugiero refactorizar el código con un "pull up". Oh, necesitaríamos también un nuevo mempty
para (*)
. Podríamos abstracta estos operadores en una clase MonoidOperator
y definir Monoid
de la siguiente manera:
class (Monoid m) => MonoidOperator mo m where
mempty :: m
mappend :: m -> m -> m
instance MonoidOperator (+) m where
mempty = 0
mappend = --definition of (+)
instance MonoidOperator (*) where
--...
class Monoid m where
-...
Bueno, yo no sé cómo hacer esto todavía, pero creo que hay una solución fresca para todo esto.
Teóricamente, '+' y '*' son especializaciones de 'mappend' pero en la práctica no lo son: esta idea se implementa como [envoltorios delgados alrededor de' Num'] (http://www.haskell.org /ghc/docs/latest/html/libraries/base/Data-Monoid.html#g:3). (Y no se puede implementar de manera sensata de otra manera, para uno, tanto '+' como '*' son válidos como la operación monoide y no habría manera de especificar cuál usar). – huon
Los números forman un 'Monoid 'instancia de dos maneras diferentes: suma y producto. Realmente hay funciones duplicadas, que deberían fusionarse juntas ('map',' fmap', 'liftM',' liftA'; '(<*>)' 'ap' y muchas otras), pero no creo que' mappend' (o '(<>)' en versiones más nuevas) es una de las funciones que necesitan una combinación. – Vitus
¿Qué opinas de la edición de la primera publicación? – L01man