[英]F# Use base type of discriminated union
I'm learning F# and struggling trying to use discriminated unions.我正在学习 F# 并努力尝试使用受歧视的工会。 I have a simple case where I'm trying to use
Map.map
on a simple discriminated union of the type Map but its saying there is a type mismatch.我有一个简单的案例,我试图在
Map.map
类型的简单区分联合上使用 Map.map 但它说存在类型不匹配。 I'm basically just trying to use the type Prices as a Map我基本上只是想将价格类型用作 Map
Here is a simplified example:这是一个简化的示例:
type Prices = Prices of Map<string, int>
let GetSalePrice (prices: Prices) = prices |> Map.map (fun k v -> (k, v * 2))
Gives me this error:给我这个错误:
/Users/luke/code/chronos/Chronos.Mining/Chronos.Mining.Actors/Untitled-1(22,47): error FS0001: Type mismatch. Expecting a
'Prices -> 'a'
but given a
'Map<'b,'c> -> Map<'b,'d>'
The type 'Prices' does not match the type 'Map<'a,'b>'
Given that all I'm doing in the map function is returning the value * 2 I don't understand why I'm getting this error.鉴于我在 map function 中所做的一切都返回值 * 2 我不明白为什么会出现此错误。
You cannot " use Prices
as a Map
", because Prices
is not a Map
.您不能“将
Prices
用作Map
”,因为Prices
不是Map
。 The way you have defined it, Prices
is a different type, not at all the same as a Map
, but it contains an instance of a Map
inside it.您定义它的方式,
Prices
是一种不同的类型,与Map
,但它包含一个Map
的实例。
If this is indeed what you meant, then in order to get the Map
out of a Prices
value, you need to pattern-match on it.如果这确实是您的意思,那么为了使
Map
脱离Prices
值,您需要对其进行模式匹配。 Like this:像这样:
let GetSalePrice (Prices theMap) = theMap |> Map.map ...
Whoa, what's going on here?哇,这是怎么回事? How is
Prices theMap
different from prices: Prices
? Prices theMap
与价格有何不同prices: Prices
? Why are we putting the type name in front of the parameter rather than behind it via a colon?为什么我们将类型名称放在参数前面而不是通过冒号放在参数后面? Isn't that how types are denoted in F#?
F# 中的类型不是这样表示的吗?
You may have a bit of a confusion because you're using the same name Prices
for both the type and its constructor.您可能会有些困惑,因为您对类型及其构造函数使用了相同的名称
Prices
。 To clear this up, let me redefine your type like this:为了澄清这一点,让我重新定义你的类型,如下所示:
type PricesType = PricesCtor of Map<string, int>
Now the function would look like:现在 function 看起来像:
let GetSalePrice (PricesCtor theMap) = theMap |> Map.map ...
So you see, it's not the type that we're putting in front of the parameter.所以你看,这不是我们放在参数前面的类型。 It's the constructor.
它是构造函数。 And this declaration -
(PricesCtor theMap)
- tells the compiler that we're expecting a parameter of type PricesType
(because that's where PricesCtor
belongs), and when we get this parameter, it should be unwrapped, and the map contained within should be named theMap
.这个声明 -
(PricesCtor theMap)
- 告诉编译器我们期待一个价格类型的参数(因为那是PricesType
所属的PricesCtor
),当我们得到这个参数时,它应该被解包,并且其中包含的 map 应该被命名theMap
。
This whole process is called "pattern matching".这整个过程称为“模式匹配”。 Here, we're matching on the constructor
PricesCtor
.在这里,我们在构造函数
PricesCtor
上进行匹配。
Your original function, on the other hand, merely specified the type of the parameter.另一方面,您原来的 function 只是指定了参数的类型。 With my new type definition I might write your original function like this:
使用我的新类型定义,我可能会像这样编写您的原始 function:
let GetSalePrice (prices: PricesType) = prices |> Map.map ...
Here, we specify that our parameter should have type PricesType
, but then we're trying to use it as an argument for Map.map
, which expects a parameter of type Map<_,_>
.在这里,我们指定我们的参数应该具有价格类型,但随后我们尝试将其用作
PricesType
的Map.map
,它需要一个类型为Map<_,_>
的参数。 No wonder there is a type mismatch!难怪有类型不匹配!
Pattern matching doesn't have to be in the parameter declaration either.模式匹配也不必在参数声明中。 You can pattern-match anywhere in the code.
您可以在代码中的任何位置进行模式匹配。 To do that, use the
match
keyword.为此,请使用
match
关键字。 This is how your function may be written that way:这就是您的 function 可以这样写的方式:
let GetSalePrice prices =
match prices with
| PricesCtor theMap -> theMap |> Map.map ...
The match
keyword becomes significant as soon as your type has more than one constructor.一旦你的类型有多个构造函数,
match
关键字就变得很重要。 For example:例如:
type PricesType = PricesAsAMap of Map<string, int> | SinglePrice as int
In this case, if you specify the pattern in the parameter declaration:在这种情况下,如果您在参数声明中指定模式:
let GetSalePrice (PricesAsAMap theMap) = ...
the compiler will warn you that the pattern match is incomplete .编译器会警告您模式匹配不完整。 Indeed, your function knows what to do when given a
SinglePrice
value, but what should it do when given a ConstantPrice
?确实,您的 function 知道在给定
SinglePrice
值时该怎么做,但是在给定ConstantPrice
时应该怎么做? You haven't defined that, so the compiler will complain.你还没有定义,所以编译器会抱怨。
This setup is an occasion to use the match
keyword:此设置是使用
match
关键字的场合:
let GetSalePrice prices =
match prices with
| PricesAsAMap theMap -> theMap |> Map.map ...
| SinglePrice p -> "single item", p
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.