You can do this by making the type private. The only drawback is that you need to provide functions for accessing data:
module Pairs = type PairDivides = private { a: int; b: int } let createPairDivides ab = match a % b with | 0 -> Some { PairDivides.a = a ; b = b } | _ -> None let print div = printfn "{%d %d}" div.a div.b let tryPrint div = match div with | Some a -> print a | None -> printfn "None" let a = Pairs.createPairDivides 2 2 let b = a.Value
By providing a function to create a pair and a function to use or retrieve it if necessary, you completely eliminate the possibility of creating invalid pairs (you get None
back instead of a bad pair) without using exceptions.
The disadvantage is that you need to provide mechanisms for extracting values ββfrom pairs, since this type is now unavailable when used outside of your current module.
Having said that, there is nothing wrong with doing this through classes. You can get the same level of enforcement by creating a class if you want:
type PairDivides private (a,b) = member __.A = a member __.B = b static member Create ab = match a % b with | 0 -> Some(PairDivides(a,b)) | _ -> None PairDivides.Create 2 2 |> printfn "%A" PairDivides.Create 2 3 |> printfn "%A"
source share