/* * Copyright (c) 2013 Lars Hupel * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package shapeless import scala.language.experimental.macros import scala.reflect.macros.Context /** * A type class abstracting over the `product` operation of type classes over * types of kind `*`, as well as deriving instances using an isomorphism. */ trait ProductTypeClass[C[_]] { /** * Given a type class instance for `H`, and a type class instance for a * product, produce a type class instance for the product prepended with `H`. */ def product[H, T <: HList](CHead: C[H], CTail: C[T]): C[H :: T] /** * The empty product. */ def emptyProduct: C[HNil] /** * Given an isomorphism between `F` and `G`, and a type class instance for `G`, * produce a type class instance for `F`. */ def project[F, G](instance: => C[G], to: F => G, from: G => F): C[F] } /** * A type class abstracting additionally over the `coproduct` operation of type * classes over types of kind `*`. */ trait TypeClass[C[_]] extends ProductTypeClass[C] { /** * Given two type class instances for `L` and `R`, produce a type class * instance for the coproduct `L :+: R`. */ def coproduct[L, R <: Coproduct](CL: => C[L], CR: => C[R]): C[L :+: R] } trait TypeClassCompanion[C[_]] { object auto { implicit def derive[T] = macro TypeClass.derive_impl[C, T] } } object TypeClass { def apply[C[_], T] = macro derive_impl[C, T] def derive_impl[C[_], T](context: Context)(implicit tTag: context.WeakTypeTag[T], cTag: context.WeakTypeTag[C[Any]]): context.Expr[C[T]] = { val helper = new GenericMacros.Helper[context.type] { val c: context.type = context val expandInner = true val optimizeSingleItem = true val tpe = tTag.tpe } context.Expr[C[T]](helper.ADT.deriveInstance(cTag.tpe.typeConstructor)) } } // vim: expandtab:ts=2:sw=2