0

I am trying to define a generic framework for validation. I was thinking of using partial function to define the rules and pass them into a generic function to eval and return result. Code looks like following:

  def assert(name: TField, validator: PartialFunction[(Any*), String], input: Any*): Seq[ValidationError] = {
    if (validator.isDefinedAt(input)) {
      invalidInput(name.name, validator(input))
    } else {
      Seq.empty
    }
  }

  assert(fieldA, hasValidValue, inputValue, allowedValues)
  assert(fieldB, isPositive, input)

  // =-=-=-=--=-=-= Validation Rules =-=-=-=-=-=-=-=
  def hasValidValue[T] = PartialFunction[(T, Set[T]), String] {
    case (input, validValues) if !validValues.contains(input) => "Value not allowed"
  }

  def isPositive = PartialFunction[Long, String] {
    case value: Long if value <= 0 => "Value should always be positive"
  }

But I cannot figure out how to define partial function parameter with variable arguments on this line:

  def assert(name: TField, validator: PartialFunction[(Any*), String], input: Any*): Seq[ValidationError] = {

So, even though the above definition compiles fine, there is compiler error while actually trying to call assert:

// Error: Type mismatch, Expected: ParitalFunction[Any, String], Found: PartialFunction[(Nothing, Set[Nothing]), String]
  assert(fieldA, hasValidValue, inputValue, allowedValues)

// Error: Type mismatch, Expected: ParitalFunction[Any, String], Found: PartialFunction[Long, String]
  assert(fieldB, isPositive, input)

So how can I define this?

1 Answer 1

1

All you need to do is to change PartialFunction[(Any*), String] to PartialFunction[Seq[Any], String]. This is because the vararg input becomes a Seq[List] and this is what the validator would actually take in.

Update

Here's a working demo of how the vararg can work:

case class TField(name: String)
type ValidationError = String
def invalidInput(s: String, v: String): Seq[String] = Seq(v)

def assert(name: TField, validator: PartialFunction[Seq[Any], String], input: Any*): Seq[ValidationError] = {
  if (validator.isDefinedAt(input)) {
    invalidInput(name.name, validator(input))
  } else {
    Seq.empty
  }
}

def isPositive = PartialFunction[Seq[Any], String] {
  case value if value.length < 2 => "Value need to have at least 2 values"
  case _ => "Ok"
}

assert(TField("s"), isPositive, 5L)
assert(TField("s"), isPositive, "s1", 1, -2L, "s3")
Sign up to request clarification or add additional context in comments.

2 Comments

It complains with similar error after changing Any* to Seq[Any]. Error: Type mismatch, Expected: ParitalFunction[Seq[Any], String], Found: PartialFunction[(Nothing, Set[Nothing]), String]. I believe the problem is mapping different rule function arguments (like hasValidValue[T] = PartialFunction[(T, Set[T]), String]) to assert function's argument (PartialFunction[(Any*), String]).
See updated answer. If it's about typing, then probably a separate question. This question was about the vararg. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.