Как я могу проверить скрытый тип HashMap.Base?

Я работаю над проектом, который ссылается unordered-containers-0.2.8.0:Data.HashMap.Base.HashMap,

Модуль, содержащий значение этого типа, не указывает, откуда оно появилось в разделах импорта, и я не могу импортировать Data.HashMap.Base,

тем не мение :browsing предполагает, что тип должен быть абстрактным, по крайней мере, в некоторых случаях.

> :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 может быть передано в функции в обоих модулях (хотя это редко требуется).

Другие вопросы по тегам