penso che la cosa migliore è un membro statico:
type Bounds = { Min: float; Max: float }
with
static member Create(min: float, max:float) =
if min >= max then
invalidArg "min" "min must be less than max"
{Min=min; Max=max}
e utilizzarlo come
> Bounds.Create(3.1, 2.1);;
System.ArgumentException: min must be less than max
Parameter name: min
at FSI_0003.Bounds.Create(Double min, Double max) in C:\Users\Stephen\Documents\Visual Studio 2010\Projects\FsOverflow\FsOverflow\Script2.fsx:line 5
at <StartupCode$FSI_0005>[email protected]()
Stopped due to error
> Bounds.Create(1.1, 2.1);;
val it : Bounds = {Min = 1.1;
Max = 2.1;}
Tuttavia, come fai notare, il grande rovescio della medaglia di questo approccio non è che nulla impedisce la costruzione di un record "non valido" direttamente. Se questa è una grande preoccupazione, considerare l'utilizzo di un tipo di classe per garantire le vostre invarianti:
type Bounds(min:float, max:float) =
do
if min >= max then
invalidArg "min" "min must be less than max"
with
member __.Min = min
member __.Max = max
insieme con un modello attivo per convenienza simile a quello che si ottiene con i record (in particolare per quanto riguarda i pattern matching):
let (|Bounds|) (x:Bounds) =
(x.Min, x.Max)
tutti insieme:
> let bounds = Bounds(2.3, 1.3);;
System.ArgumentException: min must be less than max
Parameter name: min
at FSI_0002.Bounds..ctor(Double min, Double max) in C:\Users\Stephen\Documents\Visual Studio 2010\Projects\FsOverflow\FsOverflow\Script2.fsx:line 4
at <StartupCode$FSI_0003>[email protected]()
Stopped due to error
> let bounds = Bounds(1.3, 2.3);;
val bounds : Bounds
> let isMatch = match bounds with Bounds(1.3, 2.3) -> "yes!" | _ -> "no";;
val isMatch : string = "yes!"
> let isMatch = match bounds with Bounds(0.3, 2.3) -> "yes!" | _ -> "no";;
val isMatch : string = "no"
fonte
2012-12-18 02:42:03
Se non mi sbaglio, dischi non ti danno un costruttore esplicito. – Mathias
No, avresti bisogno di un sistema di tipi più forte come i tipi di raffinatezza in [F *] (http://rise4fun.com/FStar). I Contratti di codice possono far valere questo invariante in C#, ma AFAIK il controllore contratto Contratti di codice continua a non funzionare correttamente per i progetti F #. –
Si può prendere in considerazione il passaggio a strutture che offrono uguaglianza strutturale. La corrispondenza tra pattern può essere facilitata attraverso pattern attivi. Il vantaggio è che è facile applicare le varianti [utilizzando costruttori espliciti e quindi costruisci, ecc.] (Http://stackoverflow.com/questions/12600574/argument-validation-in-f-struct-constructor). – pad