Я думаю, что проблема проблемы, с которой вы сталкиваетесь, называется проблемой выражения.
Функциональный код, использующий алгебраические типы данных, расположен на одной стороне, где он должен определять исходный проблемный домен и создавать и добавлять новые функции, работающие в этом домене. С другой стороны, это довольно сложно, особенно после того, как вы разработали набор функций для добавления типов в исходный домен.
Объектно-ориентированный код находится на другой стороне проблемы. После того, как вы определили свой начальный проблемный домен, становится чрезвычайно сложно добавить новые функции, потому что все типы должны быть расширены для его реализации, но относительно легко расширить область до новых проблем.
Рассмотрим
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)
Использования OO, легко добавлять новые формы, но это трудно новые свойства или методы формы, потому что я должен изменить каждый тип.
Я не знаю, если вы когда-либо использовали шаблон посетителя в объектно-ориентированном программировании, но потребность в этом шаблоне возникает из-за трудности выражения структур, которые могут быть легко выражены алгебраическими типами данных в функциональном программировании.
Одна из замечательных особенностей F # как языка программирования общего назначения заключается в том, что вы можете решить, какой метод выражения конкретной проблемы вы хотите использовать по проблеме на основе проблем. Это дает вам огромную гибкость для выбора оптимального подхода к разработке вашего программного обеспечения.
Если вы добавляете новый случай в разграниченный союз, вы должны иметь код, соответствующий этому случаю, поэтому вам нужно изменить соответствующую функцию. (Вы можете использовать отражение, чтобы избежать этого, но оно уродливое и неэффективное) – Petr
Некоторые лекции [здесь] (http://stackoverflow.com/a/5578381/4925216) или [там] (http://fsharpforfunandprofit.com/) fppatterns /) – Sehnsucht