在函数式语言中使用比在OO语言中更简单的类型更为典型。
建模形状是一个典型的例子。
下面是一个典型的面向对象的方法:
type IShape =
abstract member Area : double
type Circle(r : float) =
member this.Area = System.Math.PI * r ** 2.0
interface IShape with
member this.Area = this.Area
type Rectangle(w : float, h : float) =
member this.Area = w * h
interface IShape with
member this.Area = this.Area
请注意,这是很容易使用这种方法来添加新的类型,我们可以引入一个Triangle
或Hexagon
类相对较少的努力。我们只需创建类型并实现接口。
相反,如果我们想要一个新的Perimeter
成员添加到我们的IShape
,我们将不得不改变每一个可能是大量的工作落实。
现在让我们来看看如何,我们可能会在函数式语言模型的形状:
type Shape =
|Circle of float
|Rectangle of float * float
[<CompilationRepresentation (CompilationRepresentationFlags.ModuleSuffix)>]
module Shape =
let area = function
|Circle r -> System.Math.PI * r ** 2.0
|Rectangle (w, h) -> w*h
现在,希望你可以看到,它更容易添加perimeter
功能,我们只需对每Shape
情况下,模式匹配和编译器可以检查我们是否对每个案例进行了详尽的实施。
相比之下,添加新的Shape
s现在要困难得多,因为我们必须返回并更改每个作用于Shape
的函数。
结果是,无论我们选择使用哪种形式的建模,都存在权衡。这个问题被称为表达问题。
您可以方便地申请第二模式您Container
问题:
type Container =
|ContainerA
|ContainerB
let containerFunction1 = function
|ContainerA -> ....
|ContainerB -> ....
在这里,您有两个或更多的情况下和独特的落实为每个个案的功能单一类型包含在模块功能,而不是类型本身。
所以你想在F#中做同样的事情,因为你可以在其中实现类和接口。 – kemiller2002
是的。一种可能是将设计完全从C#复制到F#,但是底层实现必须是派生类的一部分。例如,在容器上运行的函数应该调用'container.IsEmpty'吗?我怎样才能设计类/类型,让'add add ... ='不会修改对象的状态? – NordCoder
目前还不清楚您是否尝试在F#中执行OOP,或者您是否正在通过功能镜头来重新考虑问题。你想完成一个接口的功能吗,但是以F#惯用方式,还是你想在代码中使用字面接口? –