可重复的模式匹配 [英] Repeatable pattern matching
问题描述
类型PaymentInstrument =
|检查字符串
| CreditCard的字符串* DateTime
让printInstrumentName instrument =
与
匹配仪器|支票号码> printfn检查
| CreditCard(number,expirationDate) - > printfncard
让printRequisites乐器=
将乐器与
匹配|支票号码 - > printfn检查%s号码
| CreditCard(number,expirationDate) - > printfncard%s%Anumber expirationDate
正如您所看到的,重复相同的模式匹配逻辑在两个功能。如果我使用OOP,我将创建接口 IPaymentInstrument
,定义两个操作:
PrintInstrumentName
和 PrintRequisites
然后实施类 - 每个付款工具一个类。根据外部条件来实例化工具,例如工厂模式( PaymentInstrumentFactory
)。
如果我需要添加新的支付工具,我只需要添加一个实现 IPaymentInstrument
接口的新类并更新工厂实例化逻辑。其他使用这些类的代码保持不变。
但是,如果我使用函数式方法,我应该更新每个函数,其中此类型的模式匹配存在。
如果使用 PaymentInstrument
类型的函数会有很多问题。
如何使用函数式方法来消除这个问题?
到这样的设计决定。
类型PaymentInstrument =
|检查字符串
| CreditCard字符串* DateTime
类型操作=
{
PrintInstrumentName:单位 - >单位
PrintRequisites:单位 - >单位
}
让getTypeOperations乐器=
将乐器与
匹配|支票号码>
让printCheckNumber()= printfncheck
让printCheckRequisites()= printfncheck%s号码
{PrintInstrumentName = printCheckNumber; PrintRequisites = printCheckRequisites}
| CreditCard(number,expirationDate) - >
让printCardNumber()= printfncard
让printCardRequisites()= printfncard%s%Anumber expirationDate
{PrintInstrumentName = printCardNumber; PrintRequisites = printCardRequisites}
和用法
let card = CreditCard(124,DateTime.Now)
let operations = getTypeOperations card
operations.PrintInstrumentName()
operations.PrintRequisites()
您可以看到 getTypeOperations
函数执行工厂模式的作用。为了聚合一组函数,我使用简单的记录类型(但是,根据F#设计准则, http: //fsharp.org/specs/component-design-guidelines/ 接口比这样的决定更受欢迎,但我有兴趣用功能性方法来做,以便更好地理解它)。
我得到了我想要的 - 模式匹配现在只有一个地方。
Consider the following simple example.
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
As you can see the same pattern matching logic is repeated in two functions. If I would use OOP I would create interface IPaymentInstrument
, define two operations:
PrintInstrumentName
and PrintRequisites
and then implement classes - one per payment instrument. To instantiate instrument depending on some external conditions I would use (for example) the factory pattern (PaymentInstrumentFactory
).
If I would need to add a new payment instrument, I just need to add a new class which implements IPaymentInstrument
interface and update factory instantiating logic. Other code that uses these classes remains as is.
But if I use the functional approach I should update each function where pattern matching on this type exists.
If there will be a lot of functions using PaymentInstrument
type that will be a problem.
How to eliminate this problem using functional approach?
Using Mark Seemann's answer I came to such design decision.
type PaymentInstrument =
| Check of string
| CreditCard of string * DateTime
type Operations =
{
PrintInstrumentName : unit -> unit
PrintRequisites : unit -> unit
}
let getTypeOperations instrument =
match instrument with
| Check number->
let printCheckNumber () = printfn "check"
let printCheckRequisites () = printfn "check %s" number
{ PrintInstrumentName = printCheckNumber; PrintRequisites = printCheckRequisites }
| CreditCard (number, expirationDate) ->
let printCardNumber () = printfn "card"
let printCardRequisites () = printfn "card %s %A" number expirationDate
{ PrintInstrumentName = printCardNumber; PrintRequisites = printCardRequisites }
And usage
let card = CreditCard("124", DateTime.Now)
let operations = getTypeOperations card
operations.PrintInstrumentName()
operations.PrintRequisites()
As you can see the getTypeOperations
function executes the role of factory pattern. To aggregate functions in a one bunch I use simple record type (however, according to F# design guidelines http://fsharp.org/specs/component-design-guidelines/ interfaces are preferred to such decision but I am interested to do it in functional approach for now to understand it better).
I got what I wanted - pattern matching is in only one place for now.
这篇关于可重复的模式匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!