我有以下F#
enum
type DataType = AUCTION|TRANSACTION
我想将DataType
用作函数的参数,以便参数的值仅限于字符串AUCTION
和TRANSACTION
,
是否可以将此enum
中的项目转换为string
,或者是否有更好的方法将参数值限制为string
的一组?
答案 0 :(得分:9)
首先,正如几位人士在评论中提到的那样,您定义的类型不是枚举,而是歧视联盟。
枚举实际上只是一个给定整数的标签,在F#中,使用以下语法声明:
type DataType =
|Auction = 1
|Transaction = 2
使用此语法,您在值和关联的整数之间建立了关系,您可以使用整数来获取枚举的值,例如
let transaction = enum<DataType>(2) // Transaction
请注意,即使我们没有定义此案例,也没有什么可以阻止您说enum<DataType>(3537)
。
有关枚举的更多详细信息,请参阅:https://msdn.microsoft.com/en-us/library/dd233216.aspx
受歧视的联盟比枚举更灵活。我们来看看你的:
type DataType =
|Auction
|Transaction
此版本现在实际上是一个标准.NET类,包含两个案例标识符:Auction
和Transaction
。您可以将Auction和Transaction视为DataType
的两个类型构造函数。
受歧视的联盟并不仅限于简单的案例,您可以存储其他数据,例如
type DataType =
/// An auction with a list of bids
|Auction of Bid list
/// A transaction with some price in GBP
|Transaction of decimal<GBP>
对于Disciminated Unions,没有与整数的隐式关系,如果我们想要构造一个特定的案例,我们必须使用适当的案例标识符。
e.g。 let auction = Auction (bidlist)
有关歧视联盟的详细信息,请参阅:https://msdn.microsoft.com/en-us/library/dd233226.aspx
在这两种情况下,可以使用模式匹配来实现为每种情况转换为特定字符串。
对于被歧视的联盟:
let datatypeToString datatype =
match datatype with
|Auction -> "AUCTION"
|Transaction -> "TRANSACTION"
对于枚举:
let datatypeToString datatype =
match datatype with
|DataType.Auction -> "AUCTION"
|DataType.Transaction -> "TRANSACTION"
请注意,当您使用Enumerations时,F#会给您一个编译器警告,告诉您模式匹配的情况并不完整。这是因为Enumerations只是int
s,除了1和2之外还有很多int
s,这意味着匹配情况并非详尽无遗。
因此,我建议你坚持使用Discriminated Unions并保持详尽的模式匹配。
P.S。如果您想从string
到DataType
向另一个方向前进,我建议使用tryCreateDataType
函数,如下所示:
let tryCreateDataType str =
match str with
|"AUCTION" -> Some Auction
|"TRANSACTION" -> Some Transaction
|_ -> None
这将返回Option
,因此它将允许您安全地匹配正在成功的功能或由于无效字符串而失败。