Last active
January 24, 2020 14:12
-
-
Save danslapman/f9a46aaac90db8d8ac9ae3f34188255a to your computer and use it in GitHub Desktop.
Quirky patterns
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //https://github.com/mongodb/mongo-scala-driver/blob/master/bson/src/main/scala/org/mongodb/scala/bson/DefaultHelper.scala | |
| /** | |
| * Neat helper to obtain a default type should one not be given eg: | |
| * | |
| * {{{ | |
| * def find[T]()(implicit e: T DefaultsTo Document) { ... } | |
| * }}} | |
| * | |
| * The signature of the `find` method ensures that it can only be called if the caller can supply an object of type | |
| * `DefaultsTo[T, Document]`. Of course, the [[DefaultsTo.default]] and `[[DefaultsTo.overrideDefault]] methods make it easy to create | |
| * such an object for any type `T`. Since these methods are implicit, the compiler automatically handles the business of calling one of | |
| * them and passing the result into `find`. | |
| * | |
| * ''But how does the compiler know which method to call?'' It uses its type inference and implicit resolution rules to determine the | |
| * appropriate method. There are three cases to consider: | |
| * | |
| * 1. `find` is called with no type parameter. In this case, type T must be inferred. Searching for an implicit method that can provide | |
| * an object of type `DefaultsTo[T, Document]`, the compiler finds `default` and `overrideDefault`. `default` is chosen since it has | |
| * priority (because it's defined in a proper subclass of the trait that defines overrideDefault). As a result, T must be bound to | |
| * `Document. | |
| * | |
| * 2. `find` is called with a non-Document type parameter (e.g., `find[BsonDocument]()`). In this case, an object of type | |
| * `DefaultsTo[BsonDocument, Document]` must be supplied. Only the `overrideDefault` method can supply it, so the compiler inserts the | |
| * appropriate call. | |
| * | |
| * 3. `find` is called with `Document` as the type parameter. Again, either method is applicable, but default wins due to its higher | |
| * priority. | |
| * | |
| */ | |
| sealed class DefaultsTo[A, B] | |
| /** | |
| * Companion object for [[DefaultsTo]] | |
| */ | |
| object DefaultsTo extends LowPriorityDefaultsTo { | |
| /** | |
| * Implicitly sets a default type of B. See [[DefaultsTo]] | |
| * | |
| * @tparam B the default type | |
| * @return Defaults[B, B] instance | |
| */ | |
| implicit def default[B]: DefaultsTo[B, B] = new DefaultsTo[B, B] | |
| } | |
| /** | |
| * Lower priority defaultsTo implicit helper | |
| */ | |
| trait LowPriorityDefaultsTo { | |
| /** | |
| * Overrides the default with the set type of A. See [[DefaultsTo]] | |
| * | |
| * @tparam A The type to use | |
| * @tparam B The default type incase type A was missing | |
| * @return Defaults[A, B] instance | |
| */ | |
| implicit def overrideDefault[A, B]: DefaultsTo[A, B] = new DefaultsTo[A, B] | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| //https://github.com/monix/monix/blob/master/monix-catnap/shared/src/main/scala/monix/catnap/OrElse.scala | |
| /** A type class for prioritized implicit search. | |
| * | |
| * Useful for specifying type class instance alternatives. | |
| * Examples: | |
| * | |
| * - `Async[F] OrElse Sync[F]` | |
| * - `Concurrent[F] OrElse Async[F]` | |
| * | |
| * Inspired by the implementations in Shapeless and Algebra. | |
| */ | |
| sealed trait OrElse[+A, +B] { | |
| def fold[C](prim: A => C, sec: B => C): C | |
| def unify[C >: B](implicit ev: A <:< C): C | |
| } | |
| object OrElse extends OrElse0 { | |
| implicit def primary[A, B](implicit a: A): A OrElse B = | |
| new Primary(a) | |
| } | |
| private[catnap] abstract class OrElse0 { | |
| implicit def secondary[A, B](implicit b: B): A OrElse B = | |
| new Secondary(b) | |
| final class Primary[+A](value: A) extends OrElse[A, Nothing] { | |
| def fold[C](prim: A => C, sec: Nothing => C) = prim(value) | |
| def unify[C >: Nothing](implicit ev: <:<[A, C]): C = value | |
| } | |
| final class Secondary[+B](value: B) extends OrElse[Nothing, B] { | |
| def fold[C](prim: Nothing => C, sec: B => C) = sec(value) | |
| def unify[C >: B](implicit ev: <:<[Nothing, C]): C = value | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment