Parece que o código F # geralmente corresponde a padrões em relação aos tipos. Certamente
match opt with
| Some val -> Something(val)
| None -> Different()
parece comum.
Mas, do ponto de vista da OOP, isso se parece muito com o fluxo de controle com base em uma verificação do tipo de tempo de execução, que normalmente seria desaprovada. Para explicar, no POO você provavelmente preferiria usar sobrecarga:
type T =
abstract member Route : unit -> unit
type Foo() =
interface T with
member this.Route() = printfn "Go left"
type Bar() =
interface T with
member this.Route() = printfn "Go right"
Este é certamente mais código. OTOH, parece-me ter vantagens estruturais:
- a extensão para uma nova forma de
T
é fácil; - Não preciso me preocupar em encontrar duplicação do fluxo de controle de escolha de rota; e
- A escolha da rota é imutável, no sentido em que, uma vez que tenho uma
Foo
mão na mão, nunca mais preciso me preocupar comBar.Route()
a implementação da
Existem vantagens na correspondência de padrões com tipos que não estou vendo? É considerado idiomático ou é um recurso que não é comumente usado?
But from an OOP perspective, that looks an awful lot like control-flow based on a runtime type check, which would typically be frowned on.
parece muito dogmático. Às vezes, você deseja separar seus ops da hierarquia: talvez 1) você não possa adicionar um op a uma hierarquia porque não é o proprietário da hierarquia; 2) as classes que você deseja que o op não correspondam à sua hierarquia; 3) você pode adicionar o op à sua hierarquia, mas não quer b / c, não quer desorganizar a API da sua hierarquia com um monte de porcaria que a maioria dos clientes não usa.