Created
February 17, 2016 10:04
-
-
Save takkkun/7d5b5572efc0c59e0357 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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