F# 使用可区分联合的基类型
F# Use base type of discriminated union
我正在学习 F#,但在尝试使用可区分联合时遇到困难。我有一个简单的案例,我试图在一个简单的 Map 类型的可区分联合上使用 Map.map
,但它说存在类型不匹配。我基本上只是想将价格类型用作 Map
这是一个简化的例子:
type Prices = Prices of Map<string, int>
let GetSalePrice (prices: Prices) = prices |> Map.map (fun k v -> (k, v * 2))
给我这个错误:
/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>'
考虑到我在 map 函数中所做的只是返回值 * 2,我不明白为什么会出现此错误。
您不能“将Prices
用作Map
”,因为Prices
不是一个Map
。按照您定义它的方式,Prices
是一种不同的类型,与 Map
完全不同,但它 包含 [=19] 的一个实例=]里面。
如果这确实是您的意思,那么为了从 Prices
值中获取 Map
,您需要对其进行模式匹配。像这样:
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
.
整个过程称为"pattern matching"。在这里,我们在构造函数 PricesCtor
.
上进行匹配
另一方面,您的原始函数仅指定了参数的类型。使用我的新类型定义,我可能会像这样编写您的原始函数:
let GetSalePrice (prices: PricesType) = prices |> Map.map ...
在这里,我们指定我们的参数应具有类型 PricesType
,但随后我们试图将其用作 Map.map
的参数,它需要类型为 [=37= 的参数].难怪类型不匹配!
模式匹配也不必在参数声明中。您可以在代码中的任何位置进行模式匹配。为此,请使用 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
我正在学习 F#,但在尝试使用可区分联合时遇到困难。我有一个简单的案例,我试图在一个简单的 Map 类型的可区分联合上使用 Map.map
,但它说存在类型不匹配。我基本上只是想将价格类型用作 Map
这是一个简化的例子:
type Prices = Prices of Map<string, int>
let GetSalePrice (prices: Prices) = prices |> Map.map (fun k v -> (k, v * 2))
给我这个错误:
/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>'
考虑到我在 map 函数中所做的只是返回值 * 2,我不明白为什么会出现此错误。
您不能“将Prices
用作Map
”,因为Prices
不是一个Map
。按照您定义它的方式,Prices
是一种不同的类型,与 Map
完全不同,但它 包含 [=19] 的一个实例=]里面。
如果这确实是您的意思,那么为了从 Prices
值中获取 Map
,您需要对其进行模式匹配。像这样:
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
.
整个过程称为"pattern matching"。在这里,我们在构造函数 PricesCtor
.
另一方面,您的原始函数仅指定了参数的类型。使用我的新类型定义,我可能会像这样编写您的原始函数:
let GetSalePrice (prices: PricesType) = prices |> Map.map ...
在这里,我们指定我们的参数应具有类型 PricesType
,但随后我们试图将其用作 Map.map
的参数,它需要类型为 [=37= 的参数].难怪类型不匹配!
模式匹配也不必在参数声明中。您可以在代码中的任何位置进行模式匹配。为此,请使用 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