Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
F#中的强类型ID?_F# - Fatal编程技术网

F#中的强类型ID?

F#中的强类型ID?,f#,F#,我的应用程序中有两种实体:客户和产品。它们各自在数据库级别由UUID标识 在我的F#代码中,这可以用System.Guid表示 为了便于阅读,我添加了如下类型: open System type CustomerId = Guid type ProductId = Guid 但是,这并不妨碍我将ProductId用作CustomerId,反之亦然 我想出了一个办法来防止这种情况: open System [<Struct>] type ProductId = {

我的应用程序中有两种实体:客户和产品。它们各自在数据库级别由UUID标识

在我的F#代码中,这可以用
System.Guid
表示

为了便于阅读,我添加了如下类型:

open System

type CustomerId = Guid

type ProductId = Guid
但是,这并不妨碍我将
ProductId
用作
CustomerId
,反之亦然

我想出了一个办法来防止这种情况:

open System

[<Struct>]
type ProductId = 
  {
    Product : Guid
  }

[<Struct>]
type CustomerId = 
  {
    Customer : Guid
  }
但它增加了类型安全性:

// let customerId : CustomerId = productId // Type error
我想知道还有什么其他的方法

您可以使用以下类型:

开放系统
[]
类型ProductId=Guid的ProductId
[]
类型CustomerId=Guid的CustomerId
让productId=productId(Guid.NewGuid())
通常,我们会将一些方便的助手方法/属性直接添加到类型中:

[<Struct>]
type ProductId = private ProductId of Guid with
    static member Create () = ProductId (Guid.NewGuid())
    member this.Value = let (ProductId i) = this in i

[<Struct>]
type CustomerId = private CustomerId of Guid with
    static member Create () = CustomerId (Guid.NewGuid())
    member this.Value = let (CustomerId i) = this in i

let productId = ProductId.Create ()
productId.Value |> printfn "%A"
[]
类型ProductId=Guid为的私有ProductId,带有
静态成员Create()=ProductId(Guid.NewGuid())
成员this.Value=let(ProductId i)=i中的this
[]
类型CustomerId=Guid为的私有CustomerId,带有
静态成员Create()=CustomerId(Guid.NewGuid())
成员this.Value=let(CustomerId i)=i中的this
让productId=productId.Create()
productId.Value |>printfn“%A”

另一种不太常见但值得一提的方法是使用所谓的幻影类型。这个想法是,您将有一个通用的包装器
id这是非常有趣的。与imho合作,单案例工会已经相当麻烦,因此探索选项很好。但您必须在这里使用幻影类型吗?假设您希望它成为您现有类型的ID
type Person={Name:string;Age:int}
,您不能只说
Let fetchPerson(ID:ID):async=.
?我制作了一个:
type ID=| ID'B静态成员nw B=ID B成员this.Value=将其与ID-ID->ID匹配,以便您可以在字符串之间进行选择,GUID或int64,然后使用如下别名:
type PersonId=ID和Person={ID:PersonId Name:string}//等。
open System

[<Struct>]
type ProductId = ProductId of Guid

[<Struct>]
type CustomerId = CustomerId of Guid

let productId = ProductId (Guid.NewGuid())
[<Struct>]
type ProductId = private ProductId of Guid with
    static member Create () = ProductId (Guid.NewGuid())
    member this.Value = let (ProductId i) = this in i

[<Struct>]
type CustomerId = private CustomerId of Guid with
    static member Create () = CustomerId (Guid.NewGuid())
    member this.Value = let (CustomerId i) = this in i

let productId = ProductId.Create ()
productId.Value |> printfn "%A"
[<Struct>]
type ID<'T> = ID of System.Guid

type CustomerID = interface end
type ProductID = interface end
let newCustomerID () : ID<CustomerID> = ID(System.Guid.NewGuid())
let newProductID () : ID<ProductID> = ID(System.Guid.NewGuid())
let printID (ID g) = printfn "%s" (g.ToString())
let ci = newCustomerID ()
let pi = newProductID ()
printID ci
printID pi
ci = pi // Type mismatch. Expecting a 'ID<CustomerID>' but given a 'ID<ProductID>'