首页 > 解决方案 > 是否可以在 Fsharp 中使用窄类型?

问题描述

我认为这是微不足道的,但我已经花了一些时间,但仍然没有干净的方法:

我有一个类型:

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

有没有更简单的方法来管理这个?

更新1:

在 ADA 中,这称为约束子类型。

https://en.wikibooks.org/wiki/Ada_Programming/Type_System#Constrained_subtype

标签: typesf#

解决方案


看起来您想将引擎划分为有效引擎和其他引擎。这对于主动模式来说是一项完美的任务。如果您的代码中有字符串输入:

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

如您所见,活动模式不仅将引擎字符串划分为有效和无效引擎,而且该分区还具有引擎值的有效负载。因此,您的callingOriginalCode函数将使用原始EngineTypes参数调用,但仅当引擎类型为Dieselor时Petrol


推荐阅读