gpt4 book ai didi

f# - 如何压缩这个重复的 F# 代码?

转载 作者:行者123 更新时间:2023-12-02 06:28:01 27 4
gpt4 key购买 nike

编辑:底部可能的解决方案

我正在做一些数据工作,我需要非常小心字符串长度,这些字符串最终将以固定宽度的文本输出发送,存储在有限大小的 nvarchar 字段中,等等。我希望对这些有很好的严格输入而不是比裸 System.String 类型。

假设我有一些这样的代码来表示这些,有一些有用的模块函数可以很好地与 Result.map、Option.map 等配合使用。

module String40 =
let private MaxLength = 40
type T = private T of string
let create (s:string) = checkStringLength MaxLength s |> Result.map T
let trustCreate (s:string) = checkStringLength MaxLength s |> Result.okVal |> T
let truncateCreate (s:string) = truncateStringToLength MaxLength s |> T
let toString (T s) = s

type T with
member this.AsString = this |> toString


module String100 =
let private MaxLength = 100
type T = private T of string
let create (s:string) = checkStringLength MaxLength s |> Result.map T
let trustCreate (s:string) = checkStringLength MaxLength s |> Result.okVal |> T
let truncateCreate (s:string) = truncateStringToLength MaxLength s |> T
let toString (T s) = s

type T with
member this.AsString = this |> toString

显然,这些几乎完全重复,只是每个 block 中的模块名称和最大长度不同。

有哪些选项可以尝试减少此处的重复性?我很想拥有这样的东西:

type String40 = LengthLimitedString<40>
type String100 = LengthLimitedString<100>

tryToRetrieveString () // returns Result<string, ERRType>
|> Result.bind String40.create
  • T4 代码生成似乎不是 F# 项目的选项
  • 对于这种简单的模板,类型提供者似乎有点矫枉过正,据我所知,它们只能生成类,不能生成模块。
  • 我知道 Scott Wlaschin 的 constrained strings页面,但在他列出的“创建类型”、“实现 IWrappedString”、“创建公共(public)构造函数”步骤中,我最终得到了大致相同级别的重复代码。

这些代码块相当短,针对不同的字段长度复制/粘贴十几次也不是世界末日。但我觉得我缺少一种更简单的方法来做到这一点。

更新:

另一个注意事项是,使用这些类型的记录提供有关它们携带的类型的信息很重要:

type MyRecord = 
{
FirstName: String40;
LastName: String100;
}

而不是像

type MyRecord = 
{
FirstName: LimitedString;
LastName: LimitedString;
}


Tomas 的回答是,使用 Depended Type Provider nuget 库是一个非常好的解决方案,对于许多对其行为没有问题的人来说,这将是一个很好的解决方案。我觉得扩展和自定义有点棘手,除非我想维护我自己的类型提供程序副本,而我希望避免这种情况。

Marcelo 关于静态参数约束的建议是一条颇有成效的研究途径。他们基本上给了我我一直在寻找的东西——一个基本上是静态方法的“接口(interface)”的通用参数。然而,更重要的是它们需要内联函数才能运行,而我没有时间评估这对我的代码库有多大影响或无关紧要。

但我接受了它并对其进行了修改以使用常规的通用约束。必须实例化一个对象以获得最大长度值有点愚蠢,而且 fsharp 类型/通用代码看起来很粗糙,但从模块用户的角度来看它很干净,我可以轻松地扩展它,但我想。

    type IMaxLengthProvider = abstract member GetMaxLength: unit -> int

type MaxLength3 () = interface IMaxLengthProvider with member this.GetMaxLength () = 3
type MaxLength4 () = interface IMaxLengthProvider with member this.GetMaxLength () = 4


module LimitedString =

type T< 'a when 'a :> IMaxLengthProvider> = private T of string

let create< 't when 't :> IMaxLengthProvider and 't : (new:unit -> 't)> (s:string) =
let len = (new 't()).GetMaxLength()
match checkStringLength len s with
| Ok s ->
let x : T< 't> = s |> T
x |> Ok
| Error e -> Error e
let trustCreate< 't when 't :> IMaxLengthProvider and 't : (new:unit -> 't)> (s:string) =
let len = (new 't()).GetMaxLength()
match checkStringLength len s with
| Ok s ->
let x : T< 't> = s |> T
x
| Error e ->
let msg = e |> formErrorMessage
failwith msg

let truncateCreate< 't when 't :> IMaxLengthProvider and 't : (new:unit -> 't)> (s:string) =
let len = (new 't()).GetMaxLength()
let s = truncateStringToLength len s
let x : T< 't> = s |> T
x

let toString (T s) = s
type T< 'a when 'a :> IMaxLengthProvider> with
member this.AsString = this |> toString


module test =
let dotest () =

let getString () = "asd" |> Ok

let mystr =
getString ()
|> Result.bind LimitedString.create<MaxLength3>
|> Result.okVal
|> LimitedString.toString

sprintf "it is %s" mystr

最佳答案

我认为 BoundedString 类型提供程序来自 Dependent type provider project 可以让你做你需要的。使用项目文档中的示例,您可以执行以下操作:

type ProductDescription = BoundedString<10, 2000>
type ProductName = BoundedString<5, 50>

type Product = { Name : ProductName; Description : ProductDescription }

let newProduct (name : string) (description : string) : Product option =
match ProductName.TryCreate(name), ProductDescription.TryCreate(description) with
| Some n, Some d -> { Name = n; Description = d }
| _ -> None

我不知道有多少人在实践中使用这个项目,但它看起来很简单,而且它完全符合您的要求,因此值得一试。

关于f# - 如何压缩这个重复的 F# 代码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50455058/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com