All Downloads are FREE. Search and download functionalities are using the official Maven repository.

play.api.libs.functional.Functors.scala Maven / Gradle / Ivy

/*
 * Copyright (C) 2009-2018 Lightbend Inc. 
 */

package play.api.libs.functional

import scala.language.higherKinds

sealed trait Variant[M[_]]

trait Functor[M[_]] extends Variant[M] {
  def fmap[A, B](m: M[A], f: A => B): M[B]
}

object Functor {
  implicit val functorOption: Functor[Option] = new Functor[Option] {
    def fmap[A, B](a: Option[A], f: A => B): Option[B] = a.map(f)
  }
}

trait InvariantFunctor[M[_]] extends Variant[M] {
  def inmap[A, B](m: M[A], f1: A => B, f2: B => A): M[B]
}

trait ContravariantFunctor[M[_]] extends Variant[M] {
  def contramap[A, B](m: M[A], f1: B => A): M[B]
}

class FunctorOps[M[_], A](ma: M[A])(implicit fu: Functor[M]) {
  def fmap[B](f: A => B): M[B] = fu.fmap(ma, f)
}

class ContravariantFunctorOps[M[_], A](ma: M[A])(implicit fu: ContravariantFunctor[M]) {
  def contramap[B](f: B => A): M[B] = fu.contramap(ma, f)
}

class InvariantFunctorOps[M[_], A](ma: M[A])(implicit fu: InvariantFunctor[M]) {
  def inmap[B](f: A => B, g: B => A): M[B] = fu.inmap(ma, f, g)
}

// Work around the fact that Scala does not support higher-kinded type patterns (type variables can only be simple identifiers)
// We use case classes wrappers so we can pattern match using their extractor
sealed trait VariantExtractor[M[_]]

case class FunctorExtractor[M[_]](functor: Functor[M]) extends VariantExtractor[M]

case class InvariantFunctorExtractor[M[_]](InvariantFunctor: InvariantFunctor[M]) extends VariantExtractor[M]

case class ContravariantFunctorExtractor[M[_]](ContraVariantFunctor: ContravariantFunctor[M]) extends VariantExtractor[M]

object VariantExtractor {

  implicit def functor[M[_]: Functor]: FunctorExtractor[M] =
    FunctorExtractor(implicitly[Functor[M]])

  implicit def contravariantFunctor[M[_]: ContravariantFunctor]: ContravariantFunctorExtractor[M] =
    ContravariantFunctorExtractor(implicitly[ContravariantFunctor[M]])

  implicit def invariantFunctor[M[_]: InvariantFunctor]: InvariantFunctorExtractor[M] =
    InvariantFunctorExtractor(implicitly[InvariantFunctor[M]])

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy