gpt4 book ai didi

f# - 可重复的模式匹配

转载 作者:行者123 更新时间:2023-12-03 12:36:36 24 4
gpt4 key购买 nike

考虑以下简单示例。

type PaymentInstrument =
| Check of string
| CreditCard of string * DateTime

let printInstrumentName instrument =
match instrument with
| Check number-> printfn "check"
| CreditCard (number, expirationDate) -> printfn "card"

let printRequisites instrument =
match instrument with
| Check number -> printfn "check %s" number
| CreditCard (number, expirationDate) -> printfn "card %s %A" number expirationDate

如您所见,相同的模式匹配逻辑在两个函数中重复。如果我使用 OOP,我会创建接口(interface) IPaymentInstrument ,定义两个操作:
PrintInstrumentNamePrintRequisites
然后实现类 - 每个支付工具一个。要根据一些外部条件实例化仪器,我会使用(例如)工厂模式( PaymentInstrumentFactory)。

如果我需要添加一个新的支付工具,我只需要添加一个实现 IPaymentInstrument 的新类接口(interface)和更新工厂实例化逻辑。使用这些类的其他代码保持原样。

但是,如果我使用函数式方法,我应该更新存在这种类型的模式匹配的每个函数。

如果会有很多函数使用 PaymentInstrument类型将是一个问题。

如何使用功能方法消除此问题?

最佳答案

正如 Patryk Ćwiek 在 the comment above 中指出的那样,您遇到了 Expression Problem ,所以你必须选择一个或另一个。

如果添加更多数据类型的能力对您来说比轻松添加更多行为的能力更重要,那么基于接口(interface)的方法可能更合适。

在 F# 中,您仍然可以定义面向对象的接口(interface):

type IPaymentInstrument =
abstract member PrintInstrumentName : unit -> unit
abstract member PrintRequisites : unit -> unit

您还可以创建实现此接口(interface)的类。这里是 Check , 我会离开 CreditCard作为给读者的练习:
type Check(number : string) =
interface IPaymentInstrument with
member this.PrintInstrumentName () = printfn "check"
member this.PrintRequisites () = printfn "check %s" number

然而,如果你想走面向对象的方式,你应该开始考虑 SOLID principles ,其中之一是 Interface Segregation Principle (互联网服务提供商)。一旦你开始积极应用 ISP, you'll ultimately end up with interfaces with a single member, like this :
type IPaymentInstrumentNamePrinter =
abstract member PrintInstrumentName : unit -> unit

type IPaymentInstrumentRequisitePrinter =
abstract member PrintRequisites : unit -> unit

您仍然可以在类中实现它:
type Check2(number : string) =
interface IPaymentInstrumentNamePrinter with
member this.PrintInstrumentName () = printfn "check"
interface IPaymentInstrumentRequisitePrinter with
member this.PrintRequisites () = printfn "check %s" number

现在这开始显得有些荒谬了。如果您使用 F#,那么 为什么要费尽心思用单个成员定义接口(interface)?

为什么不使用 功能 ?

两个所需接口(interface)成员的类型均为 unit -> unit (虽然不是一个特别“功能”的类型),那么为什么不传递这些函数,并省去接口(interface)开销呢?

printInstrumentNameprintRequisites来自 OP 的功能,您已经有了所需的行为。如果您想将它们变成“实现”所需接口(interface)的多态“对象”,您可以关闭它们:
let myCheck = Check "1234"
let myNamePrinter () = printInstrumentName myCheck

在函数式编程中,我们不将这些东西称为对象,而是称为闭包。它们不是带有行为的数据,而是带有数据的行为。

关于f# - 可重复的模式匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33298466/

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