Phantom existential types in Scala - scala

I'm trying to write a value class that wraps Scala collection's Map and provides an alternative get. I'm trying to use a phantom type in the value class and tag the Key with the same type using the method member. If the result of member is Some(k) then the user should be able to call get(k) and get a V instead of an Option[V].
import scala.collection.{Map => M}
class Key[PH, K] private (val k: K) extends AnyVal
object Key {
def apply[PH, K](k: K): Key[PH, K] = new Key(k)
}
class Map[PH, K, V] private (val m: M[K, V]) extends AnyVal {
def member(k: K): Option[Key[PH, K]] = m.get(k).map(_ => Key(k))
def get(key: Key[PH, K]): V = m.get(key.k).get
}
object Map {
def apply[PH, K, V](m: M[K, V]): Map[PH, K, V] = new Map(m)
}
def withMap[K, V, T](m: M[K, V])(cont: (Map[PH, K, V] forSome { type PH }) => T): T = cont(Map(m))
withMap(M("a" -> "a")){ m =>
m.member("a") match {
case Some(v) => println(m.get(v))
case None => println(":(")
}
}
But currently it fails compiling with the following error:
found : Key[PH(in value $anonfun),String] where type +PH(in value $anonfun)
required: Key[PH(in value cont),String]
case Some(v) => println(m.get(v))
How can I convince scalac that the PHs are the same?

Destructure the existential:
withMap(M("a" -> "a")) { case m =>
m.member("a") match {
case Some(v) => println(m.get(v))
case None => println(":(")
}
}
This abbreviates
withMap(M("a" -> "a")) { case m: Map[ph, String, String] => // name the phantom type ph, name the map m =>
m.member("a") match {
case Some(v) => println(m.get(v))
case None => println(":(")
}
}
The destructuring allows m to be given a non-existential type in terms of a newly introduced type variable. This means that every occurrence of m can now have the same type.

Phantom types are meaningless. You should say what you mean: every Key belongs to a certain Map:
import scala.collection.immutable.Map // it is not safe to use Maps in general!
class KeyedMap[K, V](val m: Map[K, V]) extends AnyVal {
import KeyedMap._
def member(k: K): Option[Key[K, V, m.type]] = m.get(k).map { _ => new Key[K, V, m.type](k) }
def fromKey(k: Key[K, V, m.type]): V = m(k.k)
}
object KeyedMap {
// vvvvvvvvvvvvvv requires this parameter to be <something>.type
class Key[K, +V, M <: Map[K, V] with Singleton] private[KeyedMap](val k: K) extends AnyVal
}
object Test {
def main(args: String*): Unit = {
val m = new KeyedMap(Map("a" -> "b"))
m.member("a") match {
case Some(v) => println(m.fromKey(v))
case None => println(":(")
}
}
}

Related

When using HList with GADTs I am having to cast using asInstanceOf[H]. Is there a way to avoid the cast?

Given 2 GADT Algebras which know about each other and 2 interpreters that are mutually recursive, I am having issues having to cast from type A to type h <: HList even though in the context of the pattern match, it should be implied that type A is type h.
Is there a way to avoid the asInstanceOf[h] call in the interpreter?
abstract class KvpHList[H<:HList]
object KvpNil extends KvpHList[HNil]
case class KvpCons[H <: A :: T,A, T<:HList](head: KvpValue[A], tail: KvpHList[T])(implicit isHCons: IsHCons.Aux[H,A,T]) extends KvpHList[H] {
val hCons: IsHCons.Aux[H,A,T] = isHCons
}
abstract class KvpValue[A]
case object StringData extends KvpValue[String]
case class HListData[H <:HList](member: KvpHList[H]) extends KvpValue[H]
def hListInterpreter[H<:HList](hList: KvpHList[H]): H => String = {
hList match {
case KvpNil => (hNil: H) => "Nil"
case cons: KvpCons[H,a,t]=> {
implicit val hCons = cons.hCons
(input: H) => {
s"${kvpInterpreter(cons.head)(input.head)} :: ${hListInterpreter(cons.tail)(input.tail)}"
}
}
}
}
def kvpInterpreter[A](kvpValue: KvpValue[A]): A => String = {
kvpValue match {
case StringData => (str: String) => str
case h: HListData[h] => {
(input: A) => { // tried (input: h) as well
val toString: h => String = hListInterpreter(h.member)
toString(input.asInstanceOf[h]) // <--- CASTING :(
}
}
}
}
kvpInterpreter(HListData(KvpCons(StringData, KvpNil))).apply("Hello" :: HNil)
Since H in KvpCons is uniquely determined by A and T, KvpCons can be parametrized with two type parameters rather than three.
Type-level pattern matching is type classes
abstract class KvpHList[H <: HList]
object KvpNil extends KvpHList[HNil]
case class KvpCons[A, T <: HList](head: KvpValue[A], tail: KvpHList[T]) extends KvpHList[A :: T]
abstract class KvpValue[A]
case object StringData extends KvpValue[String]
case class HListData[H <: HList](member: KvpHList[H]) extends KvpValue[H]
trait HListInterpreter[H <: HList] {
def apply(hList: KvpHList[H]): H => String
}
object HListInterpreter {
implicit val nil: HListInterpreter[HNil] = new HListInterpreter[HNil] {
override def apply(hList: KvpHList[HNil]): HNil => String = _ => "Nil"
}
implicit def cons[A, T <: HList](implicit
headKvpInterpreter: KvpInterpreter[A],
tailHListInterpreter: HListInterpreter[T]
): HListInterpreter[A :: T] = new HListInterpreter[A :: T] {
override def apply(hList: KvpHList[A :: T]): A :: T => String = hList match {
case cons: KvpCons[_, _] => input => s"${headKvpInterpreter(cons.head)(input.head)} :: ${tailHListInterpreter(cons.tail)(input.tail)}"
}
}
}
def hListInterpreter[H <: HList](hList: KvpHList[H])(implicit hListInterp: HListInterpreter[H]): H => String = hListInterp(hList)
trait KvpInterpreter[A] {
def apply(kvpValue: KvpValue[A]): A => String
}
object KvpInterpreter {
implicit val string: KvpInterpreter[String] = new KvpInterpreter[String] {
override def apply(kvpValue: KvpValue[String]): String => String = str => str
}
implicit def hList[H <: HList : HListInterpreter]: KvpInterpreter[H] = new KvpInterpreter[H] {
override def apply(kvpValue: KvpValue[H]): H => String = kvpValue match {
case h: HListData[H] => input => {
val toString: H => String = hListInterpreter(h.member)
toString(input)
}
}
}
}
def kvpInterpreter[A](kvpValue: KvpValue[A])(a: A)(implicit kvpInterp: KvpInterpreter[A]): String = kvpInterp(kvpValue)(a)

Scala: How to use Functors for multi type parameter trait

I have and ADT which is basically a wrapper over Function1:
case class Abstract[M[_], A, B](f:M[A] => M[B]) {
def fn: M[A] => M[B] = { case x: M[A] => f(x) }
}
I want to map over these, so I defined a Functor like so:
trait AbstractAPI[E] {
type AbsO[T] = Abstract[List, E, T]
// type AbsO[T] = Abstract[List, _, T] => does not work (?)
implicit val abstractO: Functor[AbsO] = new Functor[AbsO] {
def map[A, B](fa: AbsO[A])(f: A => B): AbsO[B] = {
new Abstract(fa.fn andThen { x: List[A] => x.map{ y => f(y) } })
}
}
}
Now, to actually map over an Abstract, I'd need AbstractAPI[Int], like
case object IntAbstractAPI extends AbstractAPI[Int]
object A {
import IntAbstractAPI._
val f:List[Int] => List[String] = { case x: List[Int] => x.map{ _.toString.toLowerCase } }
val hey = (new Abstract(f)).map{ x => x.toInt }
}
or
object A extends AbstractAPI[Int] {
val f:List[Int] => List[String] = { case x: List[Int] => x.map{ _.toString.toLowerCase } }
// FINALLY!
val res = (new Abstract(f)).map{ x => x.toInt }.map{ _.toFloat + 10f }
// Abstract[List, Int, Float] = Abstract(<function1>)
}
However, in this pattern, I'd have to define case objects for every possible E. Here are my questions:
Is this the correct way to use Functors?
How can I automate the creation of the case objects for every possible E (or make the compiler infer it?)
Edit 1:
Further clarification: The above implementation works, but this one does not:
object A extends AbstractAPI {
val f:List[Int] => List[String] = { case x: List[Int] => x.map{ _.toString.toLowerCase } }
val res = (new Abstract(f)).map{ x => x.toInt }.map{ _.toFloat + 10f }
// Abstract[List, Int, Float] = Abstract(<function1>)
}
gives compilation error:
value map is not a member of Abstract[List,Int,String]
I assume this is because the compiler is not able to derive a functor for Abstract[List,Int,String]?
You can derive a functor for type parameters that you don't care about.
import cats.Functor
import cats.syntax.functor._
And I'll rename second type parameter on Abstract to X, it'll help
case class Abstract[M[_], X, A](f: M[X] => M[A]) // forget the fn bit for now
You can create typeclass instances not only with a val, but also with a def. It is allowed to have type parameters and also take other implicit (but only implicit) parameters.
type Abs1[X] = ({ type L[A] = Abstract[List, X, A] })
/*implicit*/ def abstract1[X]: Functor[Abs1[X]#L] = new Functor[Abs1[X]#L] {
override def map[A, B](fa: Abstract[List, X, A])(f: A => B): Abstract[List, X, B] =
Abstract(mx => fa.f(mx).map(f))
}
If map is all you need from a List, you can generalize further for any M[_] that has a Functor instance. Also placing it into a companion object of Abstract enables it to be found without additional imports / inheritance / etc.
object Abstract {
// Abstract.MX[M, X]#L can be replaced with Abstract[M, X, ?] if you use kind-projector
type MX[M[_], X] = ({ type L[A] = Abstract[M, X, A] })
implicit def genericFunctor[M[_]: Functor, X] = new Functor[MX[M, X]#L] {
override def map[A, B](fa: Abstract[M, X, A])(f: A => B): Abstract[M, X, B] =
Abstract(mx => fa.f(mx).map(f)) // the implementation is the same
}
}
And it works, if you import instances for whatever your M[_] is
assert {
import cats.instances.list._ // get Functor[List]
// map is automatically picked up from Functor[Abstract[List, Int, ?]]
Abstract(identity[List[Int]])
.map(Vector.range(0, _))
.map(_.mkString(""))
.f(List(1, 2, 3)) == List("0", "01", "012")
}
assert {
import cats.instances.option._
Abstract(identity[Option[Int]])
.map(_ min 42)
.map(i => Range(i, i + 3))
.f(Some(11)) == Some(Range(11, 14))
}
You can try the code there
Answering your second question, you could try this implicit AbstractAPI[T] factory:
implicit def abstractAPI[T]: AbstractAPI[T] = new AbstractAPI[T] {}
Any required implicit evidence for AbstractAPI[T] should work, e.g:
def f[T : AbstractAPI]: Unit = ()
f

What is the purpose of the emptyCoproduct and coproduct methods of the TypeClass trait in Shapeless

It is not fully clear to me what is the purpose of the emptyCoProduct and coproduct methods of the TypeClass trait in Shapeless.
When would one use the TypeClass trait instead of the ProductTypeClass?
What are some examples of ways those two methods would be implemented?
Suppose I've got a simple type class:
trait Weight[A] { def apply(a: A): Int }
object Weight {
def apply[A](f: A => Int) = new Weight[A] { def apply(a: A) = f(a) }
}
And some instances:
implicit val stringWeight: Weight[String] = Weight(_.size)
implicit def intWeight: Weight[Int] = Weight(identity)
And a case class:
case class Foo(i: Int, s: String)
And an ADT:
sealed trait Root
case class Bar(i: Int) extends Root
case class Baz(s: String) extends Root
I can define a ProductTypeClass instance for my type class:
import shapeless._
implicit object WeightTypeClass extends ProductTypeClass[Weight] {
def emptyProduct: Weight[HNil] = Weight(_ => 0)
def product[H, T <: HList](hw: Weight[H], tw: Weight[T]): Weight[H :: T] =
Weight { case (h :: t) => hw(h) + tw(t) }
def project[F, G](w: => Weight[G], to: F => G, from: G => F): Weight[F] =
Weight(f => w(to(f)))
}
And use it like this:
scala> object WeightHelper extends ProductTypeClassCompanion[Weight]
defined object WeightHelper
scala> import WeightHelper.auto._
import WeightHelper.auto._
scala> implicitly[Weight[Foo]]
res0: Weight[Foo] = Weight$$anon$1#4daf1b4d
scala> implicitly[Weight[Bar]]
res1: Weight[Bar] = Weight$$anon$1#1cb152bb
scala> implicitly[Weight[Baz]]
res2: Weight[Baz] = Weight$$anon$1#74930887
But!
scala> implicitly[Weight[Root]]
<console>:21: error: could not find implicit value for parameter e: Weight[Root]
implicitly[Weight[Root]]
^
This is a problem—it makes our automated type class instance derivation pretty much useless for ADTs. Fortunately we can use TypeClass instead:
implicit object WeightTypeClass extends TypeClass[Weight] {
def emptyProduct: Weight[HNil] = Weight(_ => 0)
def product[H, T <: HList](hw: Weight[H], tw: Weight[T]): Weight[H :: T] =
Weight { case (h :: t) => hw(h) + tw(t) }
def project[F, G](w: => Weight[G], to: F => G, from: G => F): Weight[F] =
Weight(f => w(to(f)))
def emptyCoproduct: Weight[CNil] = Weight(_ => 0)
def coproduct[L, R <: Coproduct]
(lw: => Weight[L], rw: => Weight[R]): Weight[L :+: R] = Weight {
case Inl(h) => lw(h)
case Inr(t) => rw(t)
}
}
And then:
scala> object WeightHelper extends TypeClassCompanion[Weight]
defined object WeightHelper
scala> import WeightHelper.auto._
import WeightHelper.auto._
scala> implicitly[Weight[Root]]
res0: Weight[Root] = Weight$$anon$1#7bc44e19
All the other stuff above still works as well.
To sum up: Shapeless's Coproduct is a kind of abstraction over ADTs, and in general you should provide instances of TypeClass for your type classes instead of just ProductTypeClass whenever possible.
As of shapeless 2.3.2, the above example doesn't seem to compile. here's the updated one for future reference:
import shapeless._
import shapeless.test._
trait Weight[A] { def apply(a: A): Int }
object Weight {
def apply[A](f: A => Int) = new Weight[A] { def apply(a: A) = f(a) }
}
case class Foo(i: Int, s: String)
sealed trait Root
case class Bar(i: Int) extends Root
case class Baz(s: String) extends Root
object Base {
implicit val stringWeight: Weight[String] = Weight(_.size)
implicit def intWeight: Weight[Int] = Weight(identity)
}
object ProductTC {
object WeightHelper extends ProductTypeClassCompanion[Weight] {
object typeClass extends ProductTypeClass[Weight] {
def emptyProduct: Weight[HNil] = Weight(_ => 0)
def product[H, T <: HList](hw: Weight[H], tw: Weight[T]): Weight[H :: T] =
Weight { case (h :: t) => hw(h) + tw(t) }
def project[F, G](w: => Weight[G], to: F => G,from: G => F): Weight[F] =
Weight(f => w(to(f)))
}
}
import Base._
import WeightHelper._
implicitly[Weight[Foo]]
implicitly[Weight[Bar]]
implicitly[Weight[Baz]]
illTyped("implicitly[Weight[Root]]")
}
object TC {
object WeightTypeClass extends TypeClassCompanion[Weight] {
object typeClass extends TypeClass[Weight] {
def emptyProduct: Weight[HNil] = Weight(_ => 0)
def product[H, T <: HList](hw: Weight[H], tw: Weight[T]): Weight[H :: T] =
Weight { case (h :: t) => hw(h) + tw(t) }
def project[F, G](w: => Weight[G], to: F => G, from: G => F): Weight[F] =
Weight(f => w(to(f)))
def emptyCoproduct: Weight[CNil] = Weight(_ => 0)
def coproduct[L, R <: Coproduct]
(lw: => Weight[L], rw: => Weight[R]): Weight[L :+: R] = Weight {
case Inl(h) => lw(h)
case Inr(t) => rw(t)
}
}
}
import Base._
import WeightTypeClass._
implicitly[Weight[Root]]
}

Generic `implicit` operators for monads?

This is part programming exercise and part practical.
I'd like to build an operator | in this example such that:
val x: Option[Int] = _
def fail: Nothing = _
val result = x | fail
I have this so far and it doesn't compile:
import language.implicitConversions
import scala.util.{Try, Success, Failure}
trait OrAbleFacilitator[T] {
def apply[U](t: T, u: => U): U
}
implicit val OptionOrAbleFacilitator = new OrAbleFacilitator[Option[T]] {
def apply[U, U >: T](t: Option[T], u: => U): U = {
t match {
case Some(v) => v
case _ => u
}
}
}
implicit val TryOrAbleFacilitator = new OrAbleFacilitator[Try[T]] {
def apply[U, U >: T](t: Try[T], u: => U): U = {
t match {
case Success(v) => v
case _ => u
}
}
}
implicit class OrAble[T](t: T) {
def |[U](u: => U)(implicit orFacilitator: OrAbleFacilitator[T, U]): U = {
orFacilitator(t, u)
}
}
What am I doing wrong?
I moved a bunch of little things to get things to work. I tried to comment most places I made changes to get it running.
import language.implicitConversions
import scala.util.{Try, Success, Failure}
// you need to wrap this all in an object, since you can't have vals at the top level
object Main extends App {
// you need to capture in the trait that you are abstracting of a
// * → * kind, that is to say it needs to be a type which takes a type
// as input and returns you a type, such as Option or Try or List.. The thing you are creating an
// orable for is going to have to be in the shape F[A], not just F,
// and there is no reason to fix the inner type
trait OrAbleFacilitator[F[_]] {
// the first parameter to apply needs to be F[T], and the return type must be a supertype of T
def apply[T, U >: T](t: F[T], u: => U): U
}
implicit val OptionOrAbleFacilitator = new OrAbleFacilitator[Option] {
// here we need to accept the types for the input and output, adn they must be realted
def apply[T, U >: T](t: Option[T], u: => U): U = {
t match {
case Some(v) => v
case _ => u
}
}
}
implicit val TryOrAbleFacilitator = new OrAbleFacilitator[Try] {
def apply[T, U >: T](t: Try[T], u: => U): U = {
t match {
case Success(v) => v
case _ => u
}
}
}
// we can't just wrap any old T, it has to be something in the shape
// F[T] moved the implcit up to where we create the class so that it
// doesn't cuase us to have an additional parameter list on our |
// function ( which would prevent us from using it inline )
implicit class OrAble[F[_], T](t: F[T])(implicit or: OrAbleFacilitator[F]) {
// the vertical bar | is already a keyword in scala, I used the formal "disjunction" operatior (|) instead.
def |[U >: T](u: => U): U = {
or(t, u)
}
}
// and it works:
val noneint: Option[Int] = None
val failint: Try[Int] = Failure(new Exception())
assert((Some(0) : Option[Int]) .|(Some(1)) == 0)
assert((noneint | 2) == 2)
assert(((Success(0) : Try[Int]) | 3) == 0)
assert((failint | 4) == 4)
}

How do I use pattern matching with parametrized traits?

I have trouble with Scala traits and type erasure. I have this trait:
trait Meta[T] {
def ~=(e: T): Boolean
}
Now I want to use pattern matching to check for this case:
(m,i) match {
case (x:Meta[T], y: T) if x ~= y => println ("right")
case _ => println ("wrong")}
The T from x: Meta[T] should be the type of y or y should be a subtype of T.
If the types don't match I get an ClassCastException. But x ~= y should not be executed if the types are not correct. Is there a away around this or do I have to catch the exception and handle it that way?
I made an running example as short as possible:
trait Meta[T] {
type t = T
def ~=(e: T): Boolean
}
sealed abstract class A
case class Ide(s: String) extends A
case class MIde(s: String) extends A with Meta[A] {
def ~=(e: A) = e match {
case e: Ide => true
case e: MIde => false
}
}
sealed abstract class B
case class Foo(s: String) extends B
object Test {
def m = MIde("x")
def i = Ide("i")
def f = Foo("f")
def main[T](args: Array[String]) {
(m, i) match {
case (x: Meta[T], y: T) if x ~= y => println("right")
case _ => println("wrong")
}
// -> right
(m, f) match {
case (x: Meta[T], y: T) if x ~= y => println("right")
case _ => println("wrong")
}
// -> Exception in thread "main" java.lang.ClassCastException:
// Examples.Foo cannot be cast to Examples.A
}
}
UPDATE: added alternative at the end.
You are experiencing the limitations of pattern matching when it comes to generic types, due to type erasure.
All is not lost however. We can rely on ClassManifests to implement a generic method to convert your classes to a target type T (and another similar on to convert to Meta[T]):
trait Meta[T] { this: T =>
type t = T
def metaManifest: ClassManifest[T]
def ~=(e: T): Boolean
}
abstract sealed class Base {
def as[T:ClassManifest]: Option[T] = {
if ( classManifest[T].erasure.isAssignableFrom( this.getClass ) ) Some( this.asInstanceOf[T] )
else None
}
def asMeta[T:ClassManifest]: Option[T with Meta[T]] = {
this match {
case meta: Meta[_] if classManifest[T] <:< meta.metaManifest => as[T].asInstanceOf[Option[T with Meta[T]]]
case _ => None
}
}
}
abstract sealed class A extends Base
case class Ide(s: String) extends A
case class MIde(s: String) extends A with Meta[A] {
val metaManifest = classManifest[A]
def ~=(e: A) = e match {
case e: Ide => true
case e: MIde => false
}
}
sealed abstract class B extends Base
case class Foo(s: String) extends B
Let's test this in the REPL:
scala> m.as[A]
res17: Option[A] = Some(MIde(x))
scala> m.asMeta[A]
res18: Option[A with Meta[A]] = Some(MIde(x))
scala> i.as[A]
res19: Option[A] = Some(Ide(i))
scala> i.asMeta[A]
res20: Option[A with Meta[A]] = None
scala> f.as[A]
res21: Option[A] = None
scala> f.asMeta[A]
res22: Option[A with Meta[A]] = None
Sounds good. Now we can rewrite our pattern matching from this:
(m, i) match {
case (x: Meta[T], y: T) if x ~= y => println("right")
case _ => println("wrong")
}
to this:
(m.asMeta[T], i.as[T]) match {
case (Some(x), Some(y)) if x ~= y => println("right")
case _ => println("wrong")
}
So your example would now look like this:
object Test {
val m = MIde("x")
val i = Ide("i")
val f = Foo("f")
def test[T:ClassManifest]() {
(m.asMeta[T], i.as[T]) match {
case (Some(x), Some(y)) if x ~= y => println("right")
case _ => println("wrong")
}
// -> right
(m.asMeta[T], f.as[T]) match {
case (Some(x), Some(y)) if x ~= y => println("right")
case _ => println("wrong")
}
}
}
UPDATE: if setting explictly metaManifest everytime you mix Meta is not an option, you can let scala automtically infer it by passing it implictly in Metas constructor. This means that Meta must now be a class, and as a consequence A and B (and all similar types that must appear as Meta's type parameter) must now be traits, as you can't mix 2 classes. So you are basically swapping a restriction for another one. Choose your favorite one.
Here we go:
abstract sealed class Meta[T]( implicit val metaManifest: ClassManifest[T] ) { this: T =>
type t = T
def ~=(e: T): Boolean
}
trait Base {
def as[T:ClassManifest]: Option[T] = {
if ( classManifest[T].erasure.isAssignableFrom( this.getClass ) ) Some( this.asInstanceOf[T] )
else None
}
def asMeta[T:ClassManifest]: Option[T with Meta[T]] = {
this match {
case meta: Meta[_] if classManifest[T] != ClassManifest.Nothing && classManifest[T] <:< meta.metaManifest => as[T].asInstanceOf[Option[T with Meta[T]]]
case _ => None
}
}
}
trait A extends Base
case class Ide(s: String) extends A
case class MIde(s: String) extends Meta[A] with A {
def ~=(e: A) = e match {
case e: Ide => true
case e: MIde => false
}
}
trait B extends Base
case class Foo(s: String) extends B
object Test {
val m = MIde("x")
val i = Ide("i")
val f = Foo("f")
def test[T:ClassManifest]() {
(m.asMeta[T], i.as[T]) match {
case (Some(x), Some(y)) if x ~= y => println("right")
case _ => println("wrong")
}
(m.asMeta[T], f.as[T]) match {
case (Some(x), Some(y)) if x ~= y => println("right")
case _ => println("wrong")
}
}
}
Finally, if neither solution suits you, you could try another one: instead of mixing Meta[T] with T, just wrap it. Meta[T] would then just be wrapper to T, and you could even add an implicit conversion from Meta[T] to its wrapped value, so that an instance of Meta[T] can effectively be used like an instance of T almost transparently.