Skip to content

Instantly share code, notes, and snippets.

@eiriktsarpalis
Last active August 29, 2015 14:14
Show Gist options
  • Save eiriktsarpalis/087775afe656ad31c311 to your computer and use it in GitHub Desktop.
Save eiriktsarpalis/087775afe656ad31c311 to your computer and use it in GitHub Desktop.
NewType in F#
// current type abbreviations in F#
type A = Guid
type B = Guid
let foo (x : A) = x.ToString()
let b = B.NewGuid()
foo(b) // type checks
// proposed newtype abbreviations
newtype A = Guid
newtype B = Guid
let foo (x : A) = x.ToString()
let b = B.NewGuid()
foo(b) // type error
// newtype abbreviations should generate explicit conversion methods
let g : Guid = B.ToGuid b
let b : B = B.FromGuid g
// alternative attribute-based approach
[<NewType>]
type A = Guid
[<NewType>]
type B = Guid
@eiriktsarpalis
Copy link
Author

Good point. My original thinking was to avoid wrapping, but introduce a mechanism to statically distinguish between instances of the same underlying type much like how units of measure work. Admittedly, this is not as trivial as I originally thought.

@eiriktsarpalis
Copy link
Author

In response to your questions:

  • From the original type. But I'm wondering what type this method call should return: B or justGuid that would have to be converted explicitly? It gets even more confusing with instance methods. What would be the return type of FSharpMap.Add in case it got renamed? I think the same problem applies to using UoM over non-numerical values.
  • I think it should be impossible to declare overrides, excluding perhaps extension methods.
  • I think it should probably be erased. The reflection tradeoff is to be expected here.

@eiriktsarpalis
Copy link
Author

In other words, the struct approach is probably the better way of solving this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment