let inline (++) (w : ^W when ^W : (static member IsMeasureAbbrev : ^tm * ^t -> unit)) (t : ^t) = (# "" t : ^tm #) let inline (--) (w : ^W when ^W : (static member IsMeasureAbbrev : ^tm * ^t -> unit)) (tm : ^tm) = (# "" tm : ^t #) open System [] type Guid<[] 'Measure> = Guid [] type string<[] 'Measure> = string // use member constraints to statically establish a measure relationship between types type UoM = | UoM with static member IsMeasureAbbrev(_ : Guid<'Measure>, _ : Guid) = () static member IsMeasureAbbrev(_ : string<'Measure>, _ : string) = () [] type processId = class end [] type taskId = class end type Entry = { ProcessId : Guid ; TaskId : Guid } with static member New() = { ProcessId = UoM ++ Guid.NewGuid() ; TaskId = UoM ++ Guid.NewGuid() } match Entry.New () with | { ProcessId = pid ; TaskId = tid } -> { ProcessId = pid ; TaskId = tid } // { ProcessId = pid ; TaskId = pid } // uncomment for type error