summaryrefslogtreecommitdiff
path: root/src/library/scala/MatchingStrategy.scala
blob: d11598bad67b1d8c7f04d48c015d7f98e7b3a076 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package scala

abstract class MatchingStrategy[M[+x]] {
  // runs the matcher on the given input
  def runOrElse[T, U](in: T)(matcher: T => M[U]): U

  def zero: M[Nothing]
  def one[T](x: T): M[T]
  def guard[T](cond: Boolean, then: => T): M[T]
  def isSuccess[T, U](x: T)(f: T => M[U]): Boolean // used for isDefinedAt

  def caseResult[T](x: T): M[T] = one(x) // used as a marker to distinguish the RHS of a case (case pat => RHS) and intermediate successes
  // when deriving a partial function from a pattern match, 
  // we need to distinguish the RHS of a case, which should not be evaluated when computing isDefinedAt,
  // from an intermediate result (which must be computed)
}

object MatchingStrategy {
  implicit object OptionMatchingStrategy extends MatchingStrategy[Option] {
    type M[+x] = Option[x]
    @inline def runOrElse[T, U](x: T)(f: T => M[U]): U = f(x) getOrElse (throw new MatchError(x))
    @inline def zero: M[Nothing] = None
    @inline def one[T](x: T): M[T] = Some(x)
    @inline def guard[T](cond: Boolean, then: => T): M[T] = if(cond) Some(then) else None
    @inline def isSuccess[T, U](x: T)(f: T => M[U]): Boolean = !f(x).isEmpty
  }
}