Tao*_*Gil 3 oop f# functional-programming pattern-matching
我开始通过精彩的网站https://fsharpforfunandprofit.com学习F#
在阅读关于将F#与标准命令式语言区分开来的四个关键概念的条目中的模式匹配时,我发现了这句话(强调我的):
这些类型的选择类型可以通过使用子类或接口在C#中进行一些模拟,但是在C# 类型系统中没有内置支持来进行这种与错误检查的详尽匹配.
这对我来说似乎很奇怪,因为我认为我们可以在C#中的接口(或抽象类中的抽象方法)中使用方法定义获得完全等效的结果:它强制执行所有继承类来实现该方法,与F#代码一样,它强制使用draw方法为所有"继承"类型提供实现.
不同的是,在功能情况下,所有的实现都是相同的方法,而在面向对象的情况下,每个执行被封装在同级别......但在概念上你在这两种情况下相同的执法,所以我不知道看到功能方法的任何好处.
我错过了什么吗?有人可以为我澄清一下吗?
关键的见解是有两种建模领域的方法(广义上讲).
我们来看一下类和接口.假设您声明IShape并制作Circle,Rectangle以及所有其他人实现它.大.你打算用什么方法IShape?让我们说吧Draw.到现在为止还挺好.
现在想象一下你实现了十几种形状.然后,几个月后,你发现自己需要另一项手术.我们称之为IsEmpty.你是做什么?您添加IsEmpty到IShape,然后你去到每个十几类,并添加IsEmpty到他们.有点麻烦,但没关系,你可以做到.
几个月后,您想要添加另一项操作.然后另一个.而另一个.你很快就厌倦了,但那仍然很好,你咬紧牙关,但你做到了.
但接下来就出现了下一个问题:正在使用你的库的其他人想要添加他们自己的操作.他们在做什么?他们无法修改IShape界面,它在你的库中.他们可以要求你这样做并重新发布图书馆(效率不高,是吗?).或者他们可以用if+ is- 即等来实现操作if (shape is Circle) { ... } else if (shape is Rectangle) { ... }.但是他们遇到了你链接的文章中描述的非常困难 - 编译器不会保护他们不会错过形状!
另一方面,采取歧视的工会.您描述了union,然后向左和向右添加所需的操作.每个操作都处理自身内部的所有情况(并且编译器会验证所有情况都已确实处理),您甚至可以在引用库的其他项目中添加新操作,而无需修改原始代码.总必杀技!
但是,在接下来的几个月里,你会发现你需要另一个案例 - 比如说Triangle.当然,您可以将此案例添加到类型中,但是您必须在每个操作中为其添加处理.更糟糕的是:那些使用你的图书馆的人 - 他们的代码在获得最新版本时会破坏,他们也必须修改他们的附加操作.乏味!
所以似乎有两种不同的互斥方式:
这是语言设计中众所周知的问题.众所周知它有自己的名字 - " 表达问题 ".实际上有一些语言可以让你拥有你的蛋糕并吃掉它--Haskell有类型类,Clojure有协议,Rust有特征等等.我见过的任何一种解决方案在实践中都不够优雅,到了让人怀疑解决表达问题是否值得.
F#没有解决这个问题[1] - 你不可能同时拥有两种方式.但是,F#至少分别支持两种方式:"开放世界"的类+接口,"封闭世界"的歧视联盟.另一方面,C#仅支持"开放世界".
更重要的是,事实证明,在实际程序中,"封闭世界"建模比"开放世界"更有用.以这种方式建模的程序变得更容易理解,越来越少,越简洁."开放世界"模型通常会在你希望你的程序在编写之后被扩展时有用,有些人你不一定知道 - 也就是"插件".这种情况确实发生了,但并不常见.
[1] 如果你不计算具有静态解决类型参数的 shenannigans ,这些参数在任何情况下都无法可靠地工作
| 归档时间: |
|
| 查看次数: |
88 次 |
| 最近记录: |