(+)
и (++)
являются только специализациями mappend
; я прав? Зачем они нужны? Это бесполезное дублирование, так как у Haskell есть эти мощные классы и тип вывода.
Пусть, скажем, мы удалим (+)
и (++)
и переименуем 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]
(Это заставляет меня мечтать.). Три и, возможно, больше, функции для одного и того же, не очень хорошо для красивого языка, который настаивает на абстракции и таких вещах, как Haskell.
Я также видел такие же повторения с монадами: fmap
то же самое или почти, как map
, (.)
, liftM
, mapM
, forM
,...
Я знаю, что существуют исторические причины для fmap
, но как насчет моноидов? Планирует ли комиссия Haskell что-то об этом? Это сломало бы некоторые коды, но я слышал, хотя я не уверен, что есть входящая версия, которая будет иметь большие изменения, что является отличным событием. Это слишком жаль... По крайней мере, вилка доступна?
ИЗМЕНИТЬ
В ответах, которые я читал, есть факт, что для чисел либо (*)
, либо (+)
может поместиться в mappend
. На самом деле, я думаю, что (*)
должен быть частью Monoid
! Посмотрите:
В настоящее время, сбрасывая функции mempty
и mconcat
, мы имеем только mappend
.
class Monoid m where
mappend :: m -> m -> m
Но мы могли бы это сделать:
class Monoid m where
mappend :: m -> m -> m
mmultiply :: m -> m -> m
Это могло бы (возможно, я пока еще не достаточно об этом) ведет себя следующим образом:
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, ...]
Фактически "mmultiply" будет просто определен только в терминах "mappend", поэтому для экземпляров Monoid
нет необходимости переопределять его! Тогда Monoid
ближе к математике; возможно, мы могли бы добавить (-)
и (/)
в класс!
Если это сработает, я думаю, что он разрешит случай Sum
и Product
, а также дублирование функций: mappend
станет (+)
, а новый mmultiply
- просто (*)
.
В основном я предлагаю рефакторинг кода с "pull up".
О, нам понадобится также новый mempty
для (*)
.
Мы могли бы абстрагировать эти операторы в классе MonoidOperator
и определить Monoid
следующим образом:
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
-...
Ну, я не знаю, как это сделать, но я думаю, что для всего этого есть классное решение.