Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove U type parameter from Auditors, Models, Factories #146

Open
deaktator opened this issue Mar 16, 2017 · 0 comments
Open

Remove U type parameter from Auditors, Models, Factories #146

deaktator opened this issue Mar 16, 2017 · 0 comments

Comments

@deaktator
Copy link
Contributor

This Will Require a Major Version Change!

But It's Probably Worth It!

We can remove the U parameter by including a type constructor Aud inside of the Auditor trait. If we retain N and B, the output of the auditor is still well typed. If we have the MorphableAuditor passed to the factory still used as the auditor for the top-level models produced by the factories, we still get back the nice values we want. We can still do things like DefaultValueAuditors (see below in the code). The nice thing is that the Scala-specific features (i.e., type constructors, Aux pattern) are only used by Scala code. Therefore, we can instantiate the stuff from Java just fine in a type-safe way. If we make changeType package private to aloha, which is fine since it's only to be used by the factory, then we should be fine.

Explore this more, but to get started in the meantime ...

import scala.language.higherKinds

type RefInfo[A] = Manifest[A]

trait Auditor[-N, +B] {
  type Aud[_]
  def success[C](n: N, sub: Seq[Aud[C]] = Nil): B
  def failure[C](sub: Seq[Aud[C]] = Nil): B
}

trait MorphableAuditor[-N, +B] extends Auditor[N, B] {
  private[aloha] def changeType[M: RefInfo]: Option[MorphableAuditor.Aux[Aud, M, Aud[M]]]
}

object MorphableAuditor {
  type Aux[A[_], N, B <: A[N]] = MorphableAuditor[N, B]{ type Aud[M] = A[M] }
}

Option Auditor

case class OptionAuditor[N]() extends MorphableAuditor[N, Option[N]] {
  type Aud[M] = Option[M]
  private[aloha] def changeType[M: RefInfo] = Option(OptionAuditor[M]())
  def success[C](n: N, sub: Seq[Aud[C]] = Nil): Option[N] = Option(n)
  def failure[C](sub: Seq[Aud[C]] = Nil): Option[N] = None
}

Tree Auditor

Covariance of A is required for this to work.

case class Tree[+A](value: Option[A], children: Seq[Tree[Any]] = Nil)
case class TreeAuditor[N]() extends MorphableAuditor[N, Tree[N]] {
  type Aud[M] = Tree[M]
  private[aloha] def changeType[M: RefInfo] = Option(TreeAuditor[M]())
  def success[C](n: N, sub: Seq[Aud[C]] = Nil): Tree[N] = Tree(Option(n), sub)
  def failure[C](sub: Seq[Aud[C]] = Nil): Tree[N] = Tree(None, sub)
}

Default Value Auditor

Provides a default value that is injected on failure.

case class DefValAud[N, +B](
    auditor: MorphableAuditor[N, B], 
    default: N
) extends MorphableAuditor[N, B] {
  type Aud[M] = auditor.Aud[M]
  private[aloha] def changeType[M: RefInfo]: Option[MorphableAuditor.Aux[Aud, M, Aud[M]]] = 
    auditor.changeType[M]
  def success[C](n: N, sub: Seq[Aud[C]] = Nil): B = auditor.success(n, sub)
  def failure[C](sub: Seq[Aud[C]] = Nil): B = success(default, sub)
}

Calling Code

// Mimic a model
case class Model[N, -A, +B](f: A => N, aud: Auditor[N, B]) extends (A => B){
  def apply(a: A) = aud.success(f(a))
}

// Create some auditors
val oad = OptionAuditor[Double]()
val oai = oad.changeType[Int].get
val dad = DefValAud(oad, Double.NaN)
val dai = dad.changeType[Int].get

val tai = TreeAuditor[Int]()
val tad = tai.changeType[Double].get
val tdai = DefValAud(tai, Int.MinValue)
val tdad = tdai.changeType[Double].get

Must use original auditor, not one from changeType for auditing the top-level model output

val m = Model((d: Double) => (d * 2).toInt, tdai)
val m1 = Model((i: Int) => i / 2d, dad)

m(2)  // : Tree[Int] = Tree(Some(4),List())
m1(3) // : Option[Double] = Some(1.5)

// : Tree[Int] = Tree(Some(1),List(Tree(None,List())))
val x = tdai.success(1, Seq(tdad.failure())) 
x.value.get  // : Int = 1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant