(+)
и (++)
являются просто специализациями 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
просто (*)
. В основном предлагаю рефакторинг кода с "подтягиванием". О, нам также понадобится новый 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
-...
Ну, я еще не знаю, как это сделать, но я думаю, что есть классное решение для всего этого.