2

This is a follow-up to my previous question:

Suppose I need to validate a data structure (e.g. XML, JSON, HttpRequest, etc.). I can define a validating function A => ValidationNel[String, B] and a wrapper class around it:

class Validate[A, B](run: A => ValidationNel[String, B]) {
  def apply(a: A) = run(a)
}

I add also methods andThen and andAlso to compose Validates:

def andThen[C](other: Validate[B, C]) = new Validate[A, C] {a =>
  this(a) flatMap (b => other(b))
}

def andAlso(other: Validate[A, B]) = new Validate[A, B] (a =>
  (this(a), other(a)) match {
     case ((Success(b), Success(b)) => Success(b)
     case (failure @ Failure(errors), Success(b)) => failure
     case (Success(b), failure @ Failure(errors)) => failure
     case (Failure(errors1), Failure(errors2)) => Failure(errors1 + errors2)
  }
)

Now I can validate a data structure as follows:

case class Header(...)
case class Payload(...)
case class Message(header: Header, payload: Payload)

val validateHeader: Validate[Header, Header] = ...

val validatePayload: Validate[Payload, Payload] = ...

type ValidateMessage = Validate[Message, Message]

val validateMessageHeader =
  new ValidateMessage(m => validateHeader(m.header); m)

val validateMessagePayload =
  new ValidateMessage(m => validatePayload(m.payload); m)

val validateMessage = validateMessageHeader andAlso validateMessagePayload

Does it make sense ? How would you suggest fix/improve it ?

5
  • 1
    Three notes: 1. ValidationNel[String, A] doesn't have a semigroup instance unless A does, so I don't understand what's going on in your andAlso. 2. Using flatMap on Validation is a pretty strong indication that you should consider \/ instead. 3. Your Validate is isomorphic to Kleisli[({ type L[x] = ValidationNel[String, x] })#L, A, B], and using that would give you a semigroup instance for free when B has a semigroup. Commented Mar 8, 2015 at 20:16
  • Thank you for the feedback ! (1) I will fix andAlso in the question (2) Hmm (3) You are right. I will try it. Commented Mar 8, 2015 at 20:46
  • @TravisBrown Kleisli[M[_], A, B] is a semigroup iff M[B] is a semigroup, is it correct ? Commented Mar 9, 2015 at 15:34
  • Ah, right—I misspoke when I said you only need a semigroup for B. Commented Mar 9, 2015 at 15:46
  • This question isn't clear. You ask how we might fix or improve it. If it needs to be fixed, what is wrong with it? If this works but you want improvement, then this is probably off topic and should go to codereview.se Commented Mar 9, 2015 at 18:21

0

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.