Вы не можете « использовать Prices
как Map
», потому что Prices
это не a Map
. Как вы его определили, Prices
- это другой тип, совсем не то же самое, что Map
, но содержит экземпляр Map
внутри него.
Если это действительно то, что вы имели в виду, то, чтобы получить Map
из значения Prices
, вам необходимо сопоставить его с шаблоном. Как это:
let GetSalePrice (Prices theMap) = theMap |> Map.map ...
Эй, что здесь происходит? Чем Prices theMap
отличается от prices: Prices
? Почему мы помещаем имя типа перед параметром, а не после него через двоеточие? Разве не так обозначаются типы в F #?
Вы можете немного запутаться, потому что вы используете одно и то же имя Prices
как для типа, так и для его конструктора. Чтобы прояснить это, позвольте мне переопределить ваш тип следующим образом:
type PricesType = PricesCtor of Map<string, int>
Теперь функция будет выглядеть так:
let GetSalePrice (PricesCtor theMap) = theMap |> Map.map ...
Итак, вы видите, это не тот тип, который мы поставив перед параметром. Это конструктор. И это объявление - (PricesCtor theMap)
- сообщает компилятору, что мы ожидаем параметр типа PricesType
(потому что ему принадлежит PricesCtor
), и когда мы получим этот параметр, он должен быть развернут, а карта, содержащаяся внутри должен называться theMap
.
Весь этот процесс называется «сопоставлением с образцом». Здесь мы сопоставляем конструктор PricesCtor
.
Ваша исходная функция, с другой стороны, просто указывала тип параметра. С моим новым определением типа я мог бы написать вашу исходную функцию следующим образом:
let GetSalePrice (prices: PricesType) = prices |> Map.map ...
Здесь мы указываем, что наш параметр должен иметь тип PricesType
, но затем мы пытаемся использовать его в качестве аргумента для Map.map
, который ожидает параметр типа Map<_,_>
. Неудивительно, что существует несоответствие типов!
Сопоставление с образцом также не обязательно должно быть в объявлении параметра. Вы можете сопоставить шаблон в любом месте кода. Для этого используйте ключевое слово match
. Вот как ваша функция может быть записана таким образом:
let GetSalePrice prices =
match prices with
| PricesCtor theMap -> theMap |> Map.map ...
Ключевое слово match
становится значимым, как только ваш тип имеет более одного конструктора. Например:
type PricesType = PricesAsAMap of Map<string, int> | SinglePrice as int
В этом случае, если вы укажете шаблон в объявлении параметра:
let GetSalePrice (PricesAsAMap theMap) = ...
, компилятор предупредит вас, что совпадение с образцом неполное . Действительно, ваша функция знает, что делать, когда задано значение SinglePrice
, но что она должна делать, когда задано ConstantPrice
? Вы не определили это, поэтому компилятор будет жаловаться.
Эта настройка - повод использовать ключевое слово match
:
let GetSalePrice prices =
match prices with
| PricesAsAMap theMap -> theMap |> Map.map ...
| SinglePrice p -> "single item", p