Почему у Haskell отсутствует литеральный синтаксис конструктора Data.Map?
Я все еще новичок в Haskell (изучая его и выключая). Мне интересно, почему у Haskell нет буквенного синтаксиса конструктора Data.Map
, такого как синтаксис конструктора Map/Hash в Clojure или Ruby. Есть ли причина? Я думал, что, поскольку Haskell имеет буквенный синтаксис конструктора для Data.List
, он должен быть один для Data.Map
.
Этот вопрос не должен быть критическим вообще. Я просто хотел бы узнать больше о Haskell через ответы.
Ответы
Ответ 1
В дополнение к уже полученным ответам (несмотря на "историческую катастрофу" ), я думаю, что также есть что сказать об использовании Data.Map
в Haskell по сравнению с Hash
в Ruby или подобных вещах; объекты, подобные карте, на других языках имеют тенденцию видеть гораздо больше пользы для общего хранилища ad-hoc.
В то время как в Haskell вы в кратчайшие сроки взломали определение data
, создание класса на других языках имеет тенденцию быть несколько тяжелым, и поэтому мы обнаруживаем, что даже для данных с хорошо известной структурой, мы просто используем Hash
или dict
или аналогичные. Тот факт, что у нас есть прямой синтаксис для этого, делает его еще более привлекательным.
Контрастность с Lisp: с помощью MAKE-HASH-TABLE
, а затем повторно SETF
ing это относительно раздражает (аналогично использованию Data.Map
), поэтому все вместо этого выбрасывается во вложенные списки, потому что это удобно.
Аналогично, я рад, что наиболее удобным выбором для хранения данных является создание новых типов, и я оставлю Data.Map
, когда я на самом деле создаю карту или хеш-таблицу как неотъемлемый компонент. Есть несколько случаев, когда я думаю, что синтаксис будет приятным (как правило, только для небольших программ отбрасывания), но в целом я не пропущу его.
Ответ 2
В отличие от Clojure и Ruby, конечные карты Haskell предоставляются в виде библиотек. У этого есть компромиссы: например, как вы заметили, нет встроенного синтаксиса для конечных карт; однако, поскольку в библиотеке мы можем (и делаем) иметь много альтернативных реализаций, и вы, как программист, можете выбрать тот, который наиболее подходит для ваших целей.
Ответ 3
Haskell имеет специальный синтаксис для списков, потому что на ленивом функциональном языке они более или менее заменяют структуры управления циклом на императивных языках. Поэтому они гораздо важнее, чем Map
в грандиозной схеме.
Кроме того, я знаю, что вы ссылались на [1,2,3]
, когда вы сказали "синтаксис списка", но я хотел добавить, что синтаксис конструктора списков может быть практически реализован в haskell-98, в этом случае конструкторы могут быть инфиксными, когда они начинают с :
, например
data Pair = Int :-- Int
Таким образом, конструктор списка :
является лишь небольшим частным случаем этого общего правила синтаксиса, который довольно изящный. Некоторые пропустили это.
Ответ 4
На самом деле я не уверен, почему никто не указал на это в ответе (там только комментарий sam boosalis), но с OverloadedLists
вы можете получить синтаксис буквально для Map
и Set
:
{-# LANGUAGE OverloadedLists #-}
import Data.Map
import Data.Set
foo :: Map Int Int
foo = [(1,2)]
bar :: Set Int
bar = [1]
оттуда это еще один шаг, чтобы получить еще более приятные карты, например:
a =: b = (a,b)
ages :: Map String Int
ages = [ "erik" =: 30
, "john" =: 45
, "peter" =: 21 ]
Хотя я лично предпочитаю явно неявное, поэтому, если я не создаю DSL, я все равно придерживаюсь fromList
и (foo, bar)
- Haskell о больших победах не о маленьких.
Ответ 5
У Haskell есть конструктор Map, но он "скрыт" (как частный метод в объектно-ориентированной парадигме). Вам рекомендуется использовать "публичные" конструкторы, такие как пустой, singleton или fromList.
Однако, если вы проверите код, доступный в https://hackage.haskell.org/package/containers-0.4.0.0/docs/src/Data-Map.html, вы получите следующее определение
data Map k a = Tip
| Bin {-# UNPACK #-} !Size !k a !(Map k a) !(Map k a)
Вы можете использовать конструкторы Tip and Bin, но это не рекомендуется.