Skip to content

Instantly share code, notes, and snippets.

@soujiro32167
Created October 8, 2019 14:33
Show Gist options
  • Save soujiro32167/f0145b2129e2ea6cf47b14b1b6a48930 to your computer and use it in GitHub Desktop.
Save soujiro32167/f0145b2129e2ea6cf47b14b1b6a48930 to your computer and use it in GitHub Desktop.
Limits of type inference
import io.circe.syntax._
import io.circe._
import io.circe.parser._
import io.circe.generic.semiauto._
import scalaz.NonEmptyList
sealed trait TType {
type Self
}
object TType {
def serialize[A <: TType](value: A#Self)(implicit enc: Encoder[A#Self]): Json = value.asJson
def deserialize[A <: TType](value: String)(implicit dec: Decoder[A#Self]): Either[Error, A#Self] = decode[A#Self](value)
}
sealed trait FirstOrderType extends TType {
type Outer[_]
type Inner
override type Self = Outer[Inner]
}
case object TInt extends TType {
type Self = Int
}
implicitly[TInt.Self =:= Int] // compiles
final case class TList(of: TType) extends TType {
type Self = List[of.Self]
// implicit val enc: Encoder[Self] = deriveEncoder
def serializeAny(any: Any)(implicit enc: Encoder[Self]): Json = any.asInstanceOf[Self].asJson
}
val fot = TList(TInt)
//implicitly[fot.of.Self =:= Int] // cannot prove that
//implicitly[fot.Self =:= List[Int]] // cannot prove that
TType.serialize[TInt.type](1)
//TType.serialize[fot.type](List(1))
//TList(TInt).serialize(List(1))
final case class TList2(of: TType) extends FirstOrderType {
override type Inner = of.Self
override type Outer[A] = List[A]
}
//
val fot2 = TList2(TInt)
implicitly[fot2.Outer[fot2.Inner] =:= List[fot2.Inner]]
//implicitly[fot2.Inner =:= Int]
//-------------------------------
sealed trait TTypeG[T] {
type Self = T
}
def serializeG[A <: TTypeG[T], T](value: T)(implicit enc: Encoder[A#Self]): Json = value.asJson
//def serializeG2[T <: TTypeG[T]](value: T)(implicit enc: Encoder[T]): Json = value.asJson
//def serializeFot[T <: FirstOrderTypeG[T]](value: T)(implicit enc: Encoder[T]): Json = value.asJson
def deserializeG[A <: TTypeG[T], T](value: String)(implicit dec: Decoder[A#Self]): Either[Error, A#Self] = decode[A#Self](value)
//def serializeG3[A <: TTypeG[T]](value: A#Self)(implicit enc: Encoder[A#Self]): Json = value.asJson
case object TIntG extends TTypeG[Int]
serializeG[TIntG.type, TIntG.Self](1)
sealed trait FirstOrderTypeG[O[_], T] extends TTypeG[O[T]] {
}
case class TListG[T](of: TTypeG[T]) extends FirstOrderTypeG[List, T] {
}
val fotG = TListG(TIntG)
implicitly[fotG.Self =:= List[Int]]
serializeG[fotG.type, fotG.Self](List(1))
//serializeG2(List(1))
deserializeG[fotG.type, fotG.Self]("[1]")
trait TListG2[T] extends FirstOrderTypeG[List, T] {
}
object TListG2 {
def apply[T]: TListG2[T] = new TListG2[T] {}
}
val fotG2 = TListG2[Int]
serializeG[fotG2.type, fotG2.Self](List(1))
//serializeG2[fotG2.Self](List(1))
deserializeG[fotG2.type, fotG2.Self]("[1]")
// -------------- F Type Poly -----------------------
//sealed trait FOTConstrained[O[_], T] extends TTypeG[O[T]]
//
//object FOTConstrained {
// def apply[O[_], T <: TTypeG[T]]: FOTConstrained[O, T] = new FOTConstrained[O, T] {}
//}
//
//val fotC = FOTConstrained[List, TIntG.type]
// ------ RECORDS -------
case class TRecordG(name: String, args: NonEmptyList[(String, TTypeG[_])]) extends TTypeG[TRecordG.Record] {
}
object TRecordG {
case class Record(name: String, values: Map[String, TTypeG[_]#Self])
}
val recG = TRecordG("rec", NonEmptyList(
"i" -> TIntG,
"l" -> TListG(TIntG)
))
//serializeG[recG.type, recG.Self](TRecordG.Record("rec", Map("i" -> 1, "l" -> List(1))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment