Types 可以将窄类型与Fsharp一起使用吗?
我会认为这是一件小事,但我已经花了一些时间在这件事上,仍然没有干净的方法来做: 我有这样一种类型:Types 可以将窄类型与Fsharp一起使用吗?,types,f#,Types,F#,我会认为这是一件小事,但我已经花了一些时间在这件事上,仍然没有干净的方法来做: 我有这样一种类型: type EngineTypes = | Petrol | Diesel | Kerosene 我有一大堆函数来处理这些问题 我想制作一个更窄的类型,并且仍然使用这个新类型的原始函数 type ValidEngineType = | Petrol | Diesel 我实现这一目标的唯一方法是: type ValidEngineType = | Valid of engi
type EngineTypes =
| Petrol
| Diesel
| Kerosene
我有一大堆函数来处理这些问题
我想制作一个更窄的类型,并且仍然使用这个新类型的原始函数
type ValidEngineType =
| Petrol
| Diesel
我实现这一目标的唯一方法是:
type ValidEngineType =
| Valid of engine : EngineType
| NotValid
let validEngineCheck (engine): ValidEngineType =
match region with
| "petrol" -> Valid EngineType.Petrol
| "diesel" -> Valid EngineType.Diesel
| _ -> Invalid
后面的代码:
let myEngine = "petrol"
let checkEngine:Option<EngineType> =
match (validEngineCheck myEngine) with
| Valid engine -> Some engine
| Invalid ->
Console.Error.WriteLine("Unsupported engine: {0}", myEngine);
None
if checkEngine.IsNone then
Console.Error.WriteLine("Unsupported engine type")
Environment.Exit 1
// it is now safe to call this
callingOriginalCode checkEngine.Value
让myEngine=“汽油机”
让checkEngine:选项=
匹配(ValidEngine检查myEngine)与
|有效引擎->某些引擎
|无效->
WriteLine(“不支持的引擎:{0}”,myEngine);
没有一个
如果选中Engine.IsNone,则
Console.Error.WriteLine(“不支持的引擎类型”)
环境。出口1
//现在可以称之为安全
callingOriginalCode检查引擎。值
有没有更简单的方法来管理
更新1:
在ADA中,这称为约束子类型
您要做的是在值构造函数的子集上以任意方式处理求和类型 可以显式建模子集并将其嵌入到超集中:
type ValidEngineTypes = Petrol | Diesel
type EngineType = Valid of ValidEngineTypes | Kerosene
(您可以对OO接口和继承做一些类似的事情,但让我们把它放在一边)
如果组合在很大程度上是任意的,并且彼此不一致,那么可以显式地为每个类型建模,然后使用Choice创建“sum”类型
type Petrol = Petrol
type Diesel = Diesel
type Kerosene = Kerosene
type EngineTypes = Choice<Petrol,Diesel,Kerosene>
type ValidEngineTypes = Choice<Petrol,Diesel>
如果您不喜欢使用ChoiceN
然后直接使用
type EngineTypes =
| PetrolEngine of Petrol
| DieselEngine of Diesel
| KeroseneEngine of Kerosene
let foo (engine: EngineTypes) =
match engine with
| PetrolEngine _petrol -> "petrol"
| DieselEngine _diesel -> "diesel"
| KeroseneEngine _kerosene -> "kerosene"
这里有些东西可以更简洁,或者更习惯,我只是想让它尽可能简单和明确,你想做的是在值构造函数的子集上以任意方式处理求和类型 可以显式建模子集并将其嵌入到超集中:
type ValidEngineTypes = Petrol | Diesel
type EngineType = Valid of ValidEngineTypes | Kerosene
(您可以对OO接口和继承做一些类似的事情,但让我们把它放在一边)
如果组合在很大程度上是任意的,并且彼此不一致,那么可以显式地为每个类型建模,然后使用Choice创建“sum”类型
type Petrol = Petrol
type Diesel = Diesel
type Kerosene = Kerosene
type EngineTypes = Choice<Petrol,Diesel,Kerosene>
type ValidEngineTypes = Choice<Petrol,Diesel>
如果您不喜欢使用ChoiceN
然后直接使用
type EngineTypes =
| PetrolEngine of Petrol
| DieselEngine of Diesel
| KeroseneEngine of Kerosene
let foo (engine: EngineTypes) =
match engine with
| PetrolEngine _petrol -> "petrol"
| DieselEngine _diesel -> "diesel"
| KeroseneEngine _kerosene -> "kerosene"
另外,这里有些东西可以更简洁,也可以更惯用,我只是想让它尽可能简单明了看起来你想把你的引擎分成有效的引擎和其他引擎。这对我来说是一项完美的任务。如果您的代码中有字符串输入:
let (|ValidEngine|_|) (engine: string) =
match engine with // case-sensitive check here
| "petrol" -> Some EngineTypes.Petrol
| "diesel" -> Some EngineTypes.Diesel
| _ -> None
你的代码就变成了
let myEngine = "petrol"
match myEngine with
| ValidEngine engine -> callingOriginalCode engine // it is now safe to call this
| _ ->
Console.Error.WriteLine("Unsupported engine type")
Environment.Exit 1
正如您所看到的,活动模式不仅将引擎字符串划分为有效引擎和无效引擎,而且该分区的有效负载也为engine value。因此,
callingOriginalCode
函数将使用原始的EngineTypes
参数调用,但仅当发动机类型为Diesel
或Petroleum
时,您才希望将发动机划分为有效发动机和其他发动机。这对我来说是一项完美的任务。如果您的代码中有字符串输入:
let (|ValidEngine|_|) (engine: string) =
match engine with // case-sensitive check here
| "petrol" -> Some EngineTypes.Petrol
| "diesel" -> Some EngineTypes.Diesel
| _ -> None
你的代码就变成了
let myEngine = "petrol"
match myEngine with
| ValidEngine engine -> callingOriginalCode engine // it is now safe to call this
| _ ->
Console.Error.WriteLine("Unsupported engine type")
Environment.Exit 1
正如您所看到的,活动模式不仅将引擎字符串划分为有效引擎和无效引擎,而且该分区的有效负载也为engine value。因此,将使用原始的
EngineTypes
参数调用callingOriginalCode
函数,但仅当发动机类型为Diesel
或Petroleum
validEngineCheck出现输入错误时才会调用该函数。此外,您也不需要在此处输入新类型,您可以返回一个选项或(更好的是,IMO)一个选项,字符串是一条错误消息,其中包含传入的无效文本。validEngineCheck似乎有输入错误。此外,您不需要在此处使用新类型,您可以返回一个选项或(更好,IMO)一个选项,字符串是一条错误消息,其中包含传入的无效文本。谢谢!我不确定它是如何与使用EngineTypes的函数一起工作的。我已经对它进行了修改!我不确定它是如何与接受EngineTypes的函数一起工作的。我已经解释过了Hanks,Sergey,这是一个有趣的问题。@Istvan您当然可以将EngineTypes
值而不是字符串进行分区,我只是想展示一下示例代码的外观,这绝对有效,我认为这是最短和最好的解决方案。谢谢,Sergey,这是一个有趣的解决方案。@Istvan您当然可以分区EngineTypes
值而不是字符串,我只是想展示示例代码的外观,这绝对有效,我认为这是最短和最好的解决方案。