F# 需要关于遵守F的开/关原则的指导#

F# 需要关于遵守F的开/关原则的指导#,f#,F#,在F#中编程时,有哪些模式可以遵循打开/关闭原则 例如,我确信F#中的模式匹配在某些情况下非常好。 但是,当您不想在每次进行新的业务案例操作时修改模式匹配结构时,有什么指导 例如: let getFullName nickName = match nickName with | "Bizmonger" | "Rico" -> "Scott Nimrod" | _ -> "not found" getFullName "Bizmonger";; 引入新病例

在F#中编程时,有哪些模式可以遵循打开/关闭原则

例如,我确信F#中的模式匹配在某些情况下非常好。 但是,当您不想在每次进行新的业务案例操作时修改模式匹配结构时,有什么指导

例如:

let getFullName nickName = 
    match nickName with
    | "Bizmonger" | "Rico" -> "Scott Nimrod"
    | _ -> "not found"

getFullName "Bizmonger";;
引入新病例时会发生什么情况


因此,我不想继续修改此函数。

正如您刚刚发现的,在本例中,添加新函数很容易(您可以说它在这方面是开放的),但添加新案例却很困难

[<AbstractClass>]
type Shape() =
    abstract member Area : double
    abstract member Perimeter : double

type Circle(r) =
    inherit Shape()

    override this.Area = Math.PI * r **2.0
    override this.Perimeter = 2.0 * Math.PI * r 

type Square(a, b) =
    inherit Shape()

    override this.Area = a*b
    override this.Perimeter = 2.0 * (a+b)
当然,你可以像在C语言中一样,在F语言中使用类/对象/接口,因此你也可以使用著名的OOP模式



顺便说一句:在任何情况下,
String
都不是实现业务案例的好选择。。。这样你就不会得到OOP O/C,也不会得到FP union类型的好东西

我认为你遇到的问题的症结就是表达式问题

使用代数数据类型的函数代码位于一侧,定义初始问题域并创建和添加在该域上运行的新函数非常重要。另一方面,这是相当困难的,尤其是当您开发了一组函数来向初始域添加类型时

面向对象的代码位于问题的另一边。一旦定义了初始问题域,就很难添加新功能,因为必须扩展所有类型才能实现它,但将域扩展到新问题相对容易

考虑

type Shape =
    |Circle of float
    |Square of float * float

module Shapes =
    let area = function
        |Circle r -> Math.PI * r ** 2.0
        |Square (a, b) -> a*b

    let perimeter = function
        |Circle r -> 2.0 * Math.PI * r
        |Square (a, b) -> 2.0 * (a + b)
在这里,添加函数很容易,因为我可以为每种类型的形状定义行为,但添加新形状很困难,因为我必须编辑每个函数

[<AbstractClass>]
type Shape() =
    abstract member Area : double
    abstract member Perimeter : double

type Circle(r) =
    inherit Shape()

    override this.Area = Math.PI * r **2.0
    override this.Perimeter = 2.0 * Math.PI * r 

type Square(a, b) =
    inherit Shape()

    override this.Area = a*b
    override this.Perimeter = 2.0 * (a+b)
[]
类型形状()=
抽象成员区:双
抽象成员周长:双
类型圆(r)=
继承形状()
覆盖此。区域=Math.PI*r**2.0
覆盖此值。周长=2.0*Math.PI*r
方形字体(a、b)=
继承形状()
覆盖此区域。区域=a*b
覆盖此。周长=2.0*(a+b)
使用OO,很容易添加新的形状,但很难创建新的属性或方法,因为我必须编辑每种类型

我不知道您是否曾在面向对象编程中使用过访问者模式,但对该模式的需求源于在函数式编程中难以表达可以用代数数据类型轻松表达的结构


F#作为一种通用编程语言的一大优点是,您可以在逐个问题的基础上决定要使用哪种方法来表达特定的问题。这为您选择软件设计的最佳方法提供了极大的灵活性。

如果您将新案例添加到区分工会,则必须使代码与此案例匹配,因此您必须修改匹配函数。(你可以使用反射来避免它,但这很难看而且没有表现力)一些讲座或嗯。。。我希望根据从数据库读取的数据将案例映射到诸如整数和字符串之类的ID是常见的。我对这个完全陌生,所以请原谅我。当然可以,但是您在这里使用
Strings
作为案例的标签(就像在C#中一样)-这没什么大不了的,但通常你会选择
类型昵称=Bizmonger | Rico |…
当然,这个例子有点糟糕,因为你只会使用枚举,但我希望你能理解