Как вернуть Data.Map из функции

Эта функция работает:

serialExpansion num = Map.fromList (zip (listOfSimpleDividers num) (powers num))

но когда я связываю:

serialExpansion :: Int -> Map
serialExpansion num = Map.fromList (zip (listOfSimpleDividers num) (powers num))

я получаю сообщение об ошибке:

simplifier.hs:46:26: Not in scope: type constructor or class `Map'

Как я должен объявить функцию?


person demas    schedule 06.12.2010    source источник


Ответы (3)


Map — это параметризованный тип данных (также называемый абстрактным типом данных). Только когда вы указываете тип для ключей и тип для значений, вы получаете полностью определенный тип.

Например, карта, которая позволяет искать Strings по Integers, имеет тип Map Integer String.

Кроме того, кажется, что вы импортировали карту с квалификацией (как и должно быть). Из-за этого вы должны использовать Map.Map вместо Map в подписи.

Таким образом, ваша функция должна иметь сигнатуру типа

 serialExpansion :: Int -> Map.Map Key Value

где Key — тип данных ключа, а Value — тип данных значения. В вашем случае, если я должен предположить, возможно, вы хотите Int для обоих Key и Value. Чтобы быть точным: вы хотите, чтобы Key совпадало с типом элементов в списке listOfSimpleDividers num, а Value совпадало с типом элементов в списке powers num. (Может помочь проверить сигнатуру типа Map.fromList, если это неясно).

К настоящему моменту вы, возможно, спросите: «Но если вы могли указать правильный тип возвращаемого значения serialExpansion, почему не может этого сделать компилятор?» Может. Именно поэтому ваш первый пример сработал. Поскольку вы пропустили сигнатуру типа, компилятор вывел ее из контекста. Как вы только что убедились, написание подписей типов может быть хорошим способом убедиться, что вы полностью понимаете свой код (вместо того, чтобы полагаться на вывод типов).

person gspr    schedule 06.12.2010
comment
Параметризованный тип данных (также называемый абстрактным типом данных) — параметризованный и абстрактный — это не одно и то же. Это независимые концепции. Тип данных может быть одним или обоими. - person timbod; 26.02.2013

Два момента, чтобы дополнить ответ gspr:

Обычной практикой является импорт конструктора типа Map без уточнения, а затем импортирование остальной части модуля с уточнением:

import Data.Map (Map)
import qualified Data.Map as Map

Это позволяет вам не писать Map.Map в ваших подписях типов везде.

Кроме того, в GHCi или Hugs вы можете использовать :t, чтобы запросить у интерактивной среды предполагаемый тип любой функции. Например, если я загружаю этот файл в GHCi:

import Data.Map (Map)
import qualified Data.Map as Map

serialExpansion num = Map.fromList (zip (listOfSimpleDividers num) (powers num))
  where
    powers = undefined
    listOfSimpleDividers = undefined

Я получаю следующее:

*Main> :t serialExpansion
serialExpansion :: (Ord k) => t -> Map k a

Если вы подставите свои собственные определения powers и listOfSimpleDividers, вы получите более конкретный тип.

person Travis Brown    schedule 06.12.2010

Я просто хотел получить карту, на которой ничего нет, а затем добавить к ней более гибкий способ.

Если вы хотите сделать что-то подобное, вам нужно Map.empty (при условии, что вы импортировали его квалифицированным).

person JonnyRaa    schedule 12.02.2015