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

scalaz.OneAnd.scala Maven / Gradle / Ivy

The newest version!
package scalaz

import scalaz.Isomorphism.{<~>, IsoFunctorTemplate}
import scalaz.std.option.{optionMonoid, none, some}
import scalaz.Ordering.orderingInstance

/** @since 7.0.3 */
final case class OneAnd[F[_], A](head: A, tail: F[A])

private sealed trait OneAndFunctor[F[_]]
    extends Functor[({type λ[α] = OneAnd[F, α]})#λ] {
  def F: Functor[F]

  override def map[A, B](fa: OneAnd[F, A])(f: A => B): OneAnd[F, B] =
    OneAnd(f(fa.head), F.map(fa.tail)(f))
}

private sealed trait OneAndApply[F[_]] extends Apply[({type λ[α] = OneAnd[F, α]})#λ] with OneAndFunctor[F] {
  def F: Applicative[F]
  def G: Plus[F]

  override def ap[A, B](fa: => OneAnd[F, A])(f: => OneAnd[F, A => B]): OneAnd[F, B] = {
    val OneAnd(hf, tf) = f
    val OneAnd(ha, ta) = fa
    OneAnd(hf(ha), G.plus(F.map(ta)(hf),
                          F.ap(G.plus(F.point(ha), ta))(tf)))
  }
}

private sealed trait OneAndAlign[F[_]] extends Align[({type λ[α] = OneAnd[F, α]})#λ] with OneAndFunctor[F] {
  def F: Align[F]

  override def alignWith[A, B, C](f: A \&/ B => C) = {
    case (OneAnd(ha, ta), OneAnd(hb, tb)) =>
      OneAnd(f(\&/.Both(ha, hb)), F.alignWith(f)(ta, tb))
  }
}

private sealed trait OneAndApplicative[F[_]] extends Applicative[({type λ[α] = OneAnd[F, α]})#λ] with OneAndApply[F] {
  def F: ApplicativePlus[F]

  def point[A](a: => A): OneAnd[F, A] = OneAnd(a, F.empty)
}

private sealed trait OneAndBind[F[_]] extends Bind[({type λ[α] = OneAnd[F, α]})#λ] with OneAndApply[F] {
  def F: Monad[F]
  def G: Plus[F]

  def bind[A, B](fa: OneAnd[F, A])(f: A => OneAnd[F, B]): OneAnd[F, B] = OneAnd(
    f(fa.head).head,
    G.plus(
      f(fa.head).tail,
      F.bind(fa.tail){ a =>
        val x = f(a)
        G.plus(F.point(x.head), x.tail)
      }
    )
  )
}

private sealed trait OneAndPlus[F[_]] extends Plus[({type λ[α] = OneAnd[F, α]})#λ] {
  def F: Applicative[F]
  def G: Plus[F]

  def plus[A](a: OneAnd[F, A], b: => OneAnd[F, A]): OneAnd[F, A] =
    OneAnd(a.head, G.plus(G.plus(a.tail, F.point(b.head)), b.tail))
}

private sealed trait OneAndMonad[F[_]] extends Monad[({type λ[α] = OneAnd[F, α]})#λ] with OneAndBind[F] with OneAndApplicative[F] {
  def F: MonadPlus[F]
  def G = F
}

private sealed trait OneAndFoldable[F[_]]
    extends Foldable1[({type λ[α] = OneAnd[F, α]})#λ] {
  def F: Foldable[F]

  override def foldMap1[A, B: Semigroup](fa: OneAnd[F, A])(f: A => B) =
    foldMap(fa)(a => some(f(a))) getOrElse f(fa.head)

  override def foldMapRight1[A, B](fa: OneAnd[F, A])(z: A => B)(f: (A, => B) => B) =
    (F.foldRight(fa.tail, none[B])((a, ob) => ob map (f(a, _)) orElse some(z(a)))
       map (f(fa.head, _)) getOrElse z(fa.head))

  override def foldMapLeft1[A, B](fa: OneAnd[F, A])(z: A => B)(f: (B, A) => B) =
    F.foldLeft(fa.tail, z(fa.head))(f)

  override def foldMap[A, B](fa: OneAnd[F, A])(f: A => B)(implicit M: Monoid[B]) =
    M.append(f(fa.head), F.foldMap(fa.tail)(f))

  override def foldRight[A, B](fa: OneAnd[F, A], z: => B)(f: (A, => B) => B) =
    f(fa.head, F.foldRight(fa.tail, z)(f))

  override def foldLeft[A, B](fa: OneAnd[F, A], z: B)(f: (B, A) => B) =
    F.foldLeft(fa.tail, f(z, fa.head))(f)
}

private sealed trait OneAndFoldable1[F[_]] extends OneAndFoldable[F] {
  def F: Foldable1[F]

  override def foldMap1[A, B](fa: OneAnd[F, A])(f: A => B)(implicit S: Semigroup[B]) =
    S.append(f(fa.head), F.foldMap1(fa.tail)(f))

  override def foldMapRight1[A, B](fa: OneAnd[F, A])(z: A => B)(f: (A, => B) => B) =
    f(fa.head, F.foldMapRight1(fa.tail)(z)(f))
}

private sealed trait OneAndTraverse[F[_]]
    extends Traverse1[({type λ[α] = OneAnd[F, α]})#λ]
    with OneAndFunctor[F] with OneAndFoldable[F] {
  def F: Traverse[F]

  def traverse1Impl[G[_],A,B](fa: OneAnd[F, A])(f: A => G[B])(implicit G: Apply[G]) =
    G.applyApplicative.traverse(fa.tail)(a => -\/(f(a)))(F)
     .fold(ftl => G.apply2(f(fa.head), ftl)(OneAnd.apply),
           tl => G.map(f(fa.head))(OneAnd(_, tl)))

  override def traverseImpl[G[_],A,B](fa: OneAnd[F, A])(f: A => G[B])(implicit G: Applicative[G]) =
    G.apply2(f(fa.head), F.traverseImpl(fa.tail)(f)(G))(OneAnd.apply)
}

private sealed trait OneAndTraverse1[F[_]]
    extends OneAndTraverse[F] with OneAndFoldable1[F] {
  def F: Traverse1[F]

  override def traverse1Impl[G[_],A,B](fa: OneAnd[F, A])(f: A => G[B])(implicit G: Apply[G]) =
    G.apply2(f(fa.head), F.traverse1Impl(fa.tail)(f)(G))(OneAnd.apply)
}

sealed abstract class OneAndInstances5 {
  implicit def oneAndFunctor[F[_]: Functor]: Functor[({type λ[α] = OneAnd[F, α]})#λ] =
    new OneAndFunctor[F] {
      def F = implicitly
    }
}

sealed abstract class OneAndInstances4 extends OneAndInstances5 {
  implicit def oneAndApply[F[_]: Applicative: Plus]: Apply[({type λ[α] = OneAnd[F, α]})#λ] =
    new OneAndApply[F] {
      def F = implicitly
      def G = implicitly
    }
  implicit def oneAndAlign[F[_]: Align]: Align[({type λ[α] = OneAnd[F, α]})#λ] =
    new OneAndAlign[F] {
      def F = implicitly
    }
}

sealed abstract class OneAndInstances3 extends OneAndInstances4 {
  implicit def oneAndApplicative[F[_]: ApplicativePlus]: Applicative[({type λ[α] = OneAnd[F, α]})#λ] =
    new OneAndApplicative[F] {
      def F = implicitly
      def G = implicitly
    }
}

sealed abstract class OneAndInstances2 extends OneAndInstances3 {
  implicit def oneAndBind[F[_]: Monad: Plus]: Bind[({type λ[α] = OneAnd[F, α]})#λ] =
    new OneAndBind[F] {
      def F = implicitly
      def G = implicitly
    }
}

sealed abstract class OneAndInstances1 extends OneAndInstances2 {
  implicit def oneAndMonad[F[_]: MonadPlus]: Monad[({type λ[α] = OneAnd[F, α]})#λ] =
    new OneAndMonad[F] {
      def F = implicitly
    }

  implicit def oneAndFoldable[F[_]: Foldable]: Foldable1[({type λ[α] = OneAnd[F, α]})#λ] =
    new OneAndFoldable[F] {
      def F = implicitly
    }
}

private sealed trait OneAndEqual[F[_], A] extends Equal[OneAnd[F, A]] {
  def OA: Equal[A]
  def OFA: Equal[F[A]]

  override def equal(a1: OneAnd[F, A], a2: OneAnd[F, A]) =
    OA.equal(a1.head, a2.head) && OFA.equal(a1.tail, a2.tail)

  override def equalIsNatural = OA.equalIsNatural && OFA.equalIsNatural
}

sealed abstract class OneAndInstances0 extends OneAndInstances1 {
  /** If you have `Foldable1[F]`, `foldMap1` and `foldRight1` are
    * nonstrict and significantly more efficient.
    */
  implicit def oneAndFoldable1[F[_]: Foldable1]: Foldable1[({type λ[α] = OneAnd[F, α]})#λ] =
    new OneAndFoldable1[F] {
      def F = implicitly
    }

  implicit def oneAndEqual[F[_], A](implicit A: Equal[A], FA: Equal[F[A]]): Equal[OneAnd[F, A]] =
    new OneAndEqual[F, A] {
      def OA = A
      def OFA = FA
    }

  implicit def oneAndTraverse[F[_]: Traverse]: Traverse1[({type λ[α] = OneAnd[F, α]})#λ] =
    new OneAndTraverse[F] {
      def F = implicitly
    }
}

sealed abstract class OneAndInstances extends OneAndInstances0 {
  implicit def oneAndPlus[F[_]: Applicative: Plus]: Plus[({type λ[α] = OneAnd[F, α]})#λ] =
    new OneAndPlus[F] {
      def F = implicitly
      def G = implicitly
    }

  implicit def oneAndTraverse1[F[_]: Traverse1]: Traverse1[({type λ[α] = OneAnd[F, α]})#λ] =
    new OneAndTraverse1[F] {
      def F = implicitly
    }

  implicit def oneAndShow[F[_], A](implicit A: Show[A], FA: Show[F[A]]): Show[OneAnd[F, A]] =
    new Show[OneAnd[F, A]] {
      override def show(f: OneAnd[F, A]) =
        Cord("OneAnd(", A.show(f.head), ",", FA.show(f.tail), ")")
    }

  implicit def oneAndOrder[F[_], A](implicit A: Order[A], FA: Order[F[A]]): Order[OneAnd[F, A]] =
    new Order[OneAnd[F, A]] with OneAndEqual[F, A] {
      def OA = A
      def OFA = FA
      def order(a1: OneAnd[F, A], a2: OneAnd[F, A]) =
        Monoid[Ordering].append(A.order(a1.head, a2.head),
                                FA.order(a1.tail, a2.tail))
    }

  implicit def oneAndSemigroup[F[_]: Applicative: Plus, A]: Semigroup[OneAnd[F, A]] =
    oneAndPlus[F].semigroup

  @deprecated("Each is deprecated", "7.1")
  implicit def oneAndEach[F[_]: Each]: Each[({type λ[α] = OneAnd[F, α]})#λ] =
    new Each[({type λ[α] = OneAnd[F, α]})#λ] {
      def each[A](fa: OneAnd[F, A])(f: A => Unit) = {
        f(fa.head)
        Each[F].each(fa.tail)(f)
      }
    }

  @deprecated("Length is deprecated", "7.1")
  implicit def oneAndLength[F[_]: Length, A]: Length[({type λ[α] = OneAnd[F, α]})#λ] =
    new Length[({type λ[α] = OneAnd[F, α]})#λ] {
      def length[A](fa: OneAnd[F, A]) = 1 + Length[F].length(fa.tail)
    }

  implicit def oneAndZip[F[_]: Zip]: Zip[({type λ[α] = OneAnd[F, α]})#λ] =
    new Zip[({type λ[α] = OneAnd[F, α]})#λ] {
      def zip[A, B](a: => OneAnd[F, A], b: => OneAnd[F, B]) =
        OneAnd((a.head, b.head), Zip[F].zip(a.tail, b.tail))
    }

  implicit def oneAndUnzip[F[_]: Unzip]: Unzip[({type λ[α] = OneAnd[F, α]})#λ] =
    new Unzip[({type λ[α] = OneAnd[F, α]})#λ] {
      def unzip[A, B](a: OneAnd[F, (A, B)]) = {
        val (fa, fb) = Unzip[F].unzip(a.tail)
        (OneAnd(a.head._1, fa), OneAnd(a.head._2, fb))
      }
    }
}

object OneAnd extends OneAndInstances with OneAndFunctions

trait OneAndFunctions {
  def oneAnd[F[_], A](hd: A, tl: F[A]): OneAnd[F, A] = OneAnd(hd, tl)

  val oneAndNelIso: NonEmptyList <~> ({type λ[α] = OneAnd[List, α]})#λ =
    new IsoFunctorTemplate[NonEmptyList, ({type λ[α] = OneAnd[List, α]})#λ] {
      def to[A](fa: NonEmptyList[A]) = OneAnd(fa.head, fa.tail)
      def from[A](ga: OneAnd[List, A]) = NonEmptyList.nel(ga.head, ga.tail)
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy