Ultimamente ho insegnato a me F # e provengo da uno sfondo imperativo (C++/C#). Come esercizio ho lavorato su funzioni che possono fare roba con matrici, come aggiungere, moltiplicare, ottenere determinanti, ecc. Tutto sta andando bene a questo proposito, ma trovo che forse non sto prendendo le decisioni migliori quando si tratta di gestire input non validi, ad esempio:F #: alcuni, nessuno o eccezione?
// I want to multiply two matrices
let mult m1 m2 =
let sizeOK = validateDims m1 m2
// Here is where I am running to conceptual trouble:
// In a C# world, I would throw an exception.
if !sizeOK then
raise (InvalidOperationException("bad dimensions!")
else
doWork m1 m2
Quindi, mentre questo funziona tecnicamente, è appropriato per un linguaggio funzionale? È nello spirito della programmazione funzionale? O sarebbe più sensato per riscrivere come:
let mult m1 m2 =
let sizeOK = validateDims m1 m2
if !sizeOK then
None
else
Some doWork m1 m2
In questo caso sto tornando un'opzione, che aggiunge un ulteriore livello intorno alla matrice, ma potrebbe anche utilizzare i risultati della funzione, anche in un fallimento casi (Nessuno) con abbinamento di pattern, ecc. in qualche momento successivo nel programma. Quindi esiste una best practice per questi tipi di scenari? Cosa farebbe un programmatore funzionale?
Credo che quest'ultimo sia più nello "spirito" di FP. Potresti voler esaminare la Forse monade e questo è un approccio comune per gestire gli input negativi. –
Come detto nella risposta, ho anche implementato spesso due funzioni, una che genera errori e una identica funzione di prova che restituisce un'opzione/scelta invece di lanciare. poi uso quello che rende il mio codice finale più carino :) per una più facile gestione di Option/Choice che potresti voler leggere "programmazione orientata alla ferrovia": http://fsharpforfunandprofit.com/posts/recipe-part2/ – stmax