Skip to content

Instantly share code, notes, and snippets.

@takkkun
Created February 17, 2016 10:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save takkkun/7d5b5572efc0c59e0357 to your computer and use it in GitHub Desktop.
Save takkkun/7d5b5572efc0c59e0357 to your computer and use it in GitHub Desktop.
class Violation(message: String)
class Funny[V](value: V) {
def validateWith(validator: Validator[V]): Validity[V] = validator(value)
}
object Funny {
def apply[V](value: V): Funny[V] = new Funny(value)
}
// Validityの合成は適当。ただし、下記のようにやってしまうと、タプルがネストしてしまうため、ValidityもValidity1やValidity2が必要だと思う。
trait Validity[+V] {
def |@|[N](validity: Validity[N]): Validity[(V, N)]
}
case class Valid[V](values: V) extends Validity[V] {
override def |@|[N](validity: Validity[N]): Validity[(V, N)] = validity match {
case Valid(newValue) => Valid((values, newValue))
case Invalid() => Invalid()
}
}
case class Invalid() extends Validity[Nothing] {
override def |@|[N](validity: Validity[N]): Validity[(Nothing, N)] = validity match {
case Valid(newValue) => Invalid()
case Invalid() => Invalid()
}
}
trait Validator[V] {
def apply(value: V): Validity[V] = {
val violations = validate(value)
if (violations.isEmpty) Valid(value) else Invalid()
}
def validate(value: V): Seq[Violation]
// 移譲してるだけなので、implicit conversionで出来るならそれでも良さそう(未確認)。
def +[V2](other: Validator[V2]): Validation2[V, V2] =
new SimpleValidation(this) + other
def flatMap[V2](depend: V => Validator[V2]): Validation2[V, V2] =
new SimpleValidation(this).flatMap(depend)
}
trait Validation1[P1] {
def apply(param1: Funny[P1]): Validity[P1]
}
trait Validation2[P1, P2] {
def apply(param1: Funny[P1], param2: Funny[P2]): Validity[(P1, P2)]
}
// こんな感じでValidationNを増やしていく。先述したようにValidityNも設ける必要ありな気がする。
class SimpleValidation[P1](validator: Validator[P1]) extends Validation1[P1] {
override def apply(param: Funny[P1]): Validity[P1] =
param.validateWith(validator)
def +[P2](other: Validator[P2]): Validation2[P1, P2] =
new Validation2[P1, P2] {
override def apply(param1: Funny[P1], param2: Funny[P2]): Validity[(P1, P2)] =
param1.validateWith(validator) |@| param2.validateWith(other)
}
def flatMap[P2](createValidator: P1 => Validator[P2]): Validation2[P1, P2] =
new Validation2[P1, P2] {
override def apply(param1: Funny[P1], param2: Funny[P2]): Validity[(P1, P2)] =
param1.validateWith(validator) match {
case valid @ Valid(values) => {
val subsequentValidator = createValidator(values)
valid |@| param2.validateWith(subsequentValidator)
}
case invalid @ Invalid() => {
invalid |@| Invalid()
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment