Как я могу проверить скрытый тип HashMap.Base?
Я работаю над проектом, который ссылается unordered-containers-0.2.8.0:Data.HashMap.Base.HashMap
,
Модуль, содержащий значение этого типа, не указывает, откуда оно появилось в разделах импорта, и я не могу импортировать Data.HashMap.Base
,
тем не мение :bro
wsing предполагает, что тип должен быть абстрактным, по крайней мере, в некоторых случаях.
> :bro Data.HashMap.Lazy
[...]
unordered-containers-0.2.8.0:Data.HashMap.Base.toList ::
unordered-containers-0.2.8.0:Data.HashMap.Base.HashMap k v
-> [(k, v)]
Означает ли это, что я могу импортировать функции из Lazy
или же Strict
варианты?
1 ответ
Да, в unordered-containers
пакет, предполагается, что вы либо импортируете Data.HashMap.Lazy
или же Data.HashMap.Strict
, Оба варианта имеют строгие ключи (оцениваются по WHNF) и отличаются тем, что значения также оцениваются по WHNF или нет.
В пакете с исходным кодом для unordered-containers
есть скрытый модуль Data.HashMap.Base
он содержит код, общий для ленивых и строгих вариантов. Поскольку этот модуль скрыт (технически, потому что он указан в файле Cabal пакета под other-modules
строфа вместо exposed-modules
раздел), он не предназначен для импорта напрямую, а только косвенно через один из двух других модулей.
За toList
в частности, выставленные модули Data.HashMap.Lazy
а также Data.HashMap.Strict
оба используют (то есть реэкспортируют) одно и то же определение toList
определено в скрытом модуле Data.HashMap.Base
Вот почему вы видите это в GHCI.
Если вы импортируете один из модулей в GHCI, вы сможете проверить toList
и типы его компонентов:
> import Data.HashMap.Strict
> :t toList
toList :: HashMap k v -> [(k, v)]
> :i HashMap
type role HashMap nominal representational
data HashMap k v
= unordered-containers-0.2.7.2:Data.HashMap.Base.Empty
...
На самом деле, вы обнаружите, что то же самое HashMap
определение используется как для строгих, так и для ленивых вариантов, поэтому это не "абстрактный" тип в том смысле, в каком вы думаете: обе реализации используют одну и ту же базовую конкретную структуру данных и отличаются тем, как ее используют функции, работающие с этой структурой данных.
Это верно для Data.Map.Strict
а также Data.Map.Lazy
Простые карты тоже, кстати. "Строгая" карта может использоваться с ленивыми операциями и наоборот, потому что "строгая" и "ленивая" карты - это один и тот же объект. Цитирование из документации для Data.Map.Lazy
:
API этого модуля строг в ключах, но ленив в значениях. Если вам нужны карты со строгим значением, используйте вместо этого Data.Map.Strict. Сам тип Map является общим для ленивых и строгих модулей, что означает, что одно и то же значение Map может быть передано в функции в обоих модулях (хотя это редко требуется).