Sembra che il codice F # spesso corrisponda al modello rispetto ai tipi. Certamente
match opt with
| Some val -> Something(val)
| None -> Different()
sembra comune.
Ma dal punto di vista OOP, assomiglia moltissimo al flusso di controllo basato su un controllo del tipo di runtime, che sarebbe normalmente disapprovato. Per spiegarlo, in OOP probabilmente preferiresti usare il sovraccarico:
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"
Questo è sicuramente più codice. OTOH, mi sembra OOP-y avere vantaggi strutturali:
- l'estensione a una nuova forma di
T
è facile; - Non devo preoccuparmi di trovare la duplicazione del flusso di controllo di scelta del percorso; e
- la scelta della rotta è immutabile, nel senso che una volta che ne ho una
Foo
in mano, non devo mai preoccuparmiBar.Route()
dell'implementazione
Ci sono vantaggi nella corrispondenza dei modelli rispetto ai tipi che non vedo? È considerato idiomatico o è una capacità che non è comunemente usata?
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.
- sembra troppo dogmatico. A volte, vuoi separare le tue operazioni dalla tua gerarchia: forse 1) non puoi aggiungere un'operazione a una gerarchia b / c che non possiedi la gerarchia; 2) le classi che vuoi avere non corrispondono alla tua gerarchia; 3) potresti aggiungere l'op alla tua gerarchia, ma non vuoi b / c non vuoi ingombrare l'API della tua gerarchia con un mucchio di schifezze che la maggior parte dei client non usa.