Skip to content

Instantly share code, notes, and snippets.

@milessabin
Last active July 23, 2017 11:17
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save milessabin/65fa0d4ef373781d3ab4 to your computer and use it in GitHub Desktop.
Save milessabin/65fa0d4ef373781d3ab4 to your computer and use it in GitHub Desktop.
Empty refinements prevent unwanted widening when assigning singleton-typed values to a val.
// Used in shapeless here: https://github.com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/syntax/singletons.scala#L42
scala> def narrow[T <: AnyRef](t: T): t.type = t
narrow: [T <: AnyRef](t: T)t.type
scala> val s1 = narrow("foo") // Widened
s1: String = foo
scala> def narrow[T <: AnyRef](t: T): t.type {} = t // Note empty refinement
narrow: [T <: AnyRef](t: T)t.type
scala> val s2 = narrow("foo") // Not widened
s2: String("foo") = foo
@nremond
Copy link

nremond commented Mar 19, 2015

Brilliant.

@kevinmeredith
Copy link

@nremond, could you please explain the difference between s1 and s2? I'm not following.

Thanks

@afijog
Copy link

afijog commented Jul 23, 2017

s1 is a String that can 'hold' any string value (type is String), while s2 can only hold the string value "foo", because type is String("foo")

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