mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-20 09:17:43 +03:00
foldLeft, foldRight, other Foldable specializations (#11592)
* FoldableContravariant, a mapping for Foldable instances * use FoldableContravariant to specialize several ImmArraySeq, NonEmpty methods * folding specializations for ImmArray * a few docs for FoldableContravariant * specializations for FrontStack * no changelog CHANGELOG_BEGIN CHANGELOG_END
This commit is contained in:
parent
92dfcdeb24
commit
b87acab897
@ -4,8 +4,6 @@
|
||||
package com.daml.lf.data
|
||||
|
||||
import ScalazEqual.{orderBy, toIterableForScalazInstances}
|
||||
import scalaz.syntax.applicative._
|
||||
import scalaz.syntax.traverse._
|
||||
import scalaz.{Applicative, Order, Traverse}
|
||||
|
||||
import scala.annotation.tailrec
|
||||
@ -154,11 +152,26 @@ object FrontStack extends FrontStackInstances {
|
||||
implicit val `FrontStack covariant`: Traverse[FrontStack] = new Traverse[FrontStack] {
|
||||
override def traverseImpl[G[_]: Applicative, A, B](
|
||||
fa: FrontStack[A]
|
||||
)(f: A => G[B]): G[FrontStack[B]] =
|
||||
)(f: A => G[B]): G[FrontStack[B]] = {
|
||||
import scalaz.syntax.applicative._, scalaz.syntax.traverse._
|
||||
fa.toBackStack.bqFoldRight(FrontStack.empty[B].pure[G])(
|
||||
(a, z) => ^(f(a), z)(_ +: _),
|
||||
(iaa, z) => ^(iaa traverse f, z)(_ ++: _),
|
||||
)
|
||||
}
|
||||
|
||||
override def map[A, B](fa: FrontStack[A])(f: A => B) = fa map f
|
||||
|
||||
override def foldLeft[A, B](fa: FrontStack[A], z: B)(f: (B, A) => B) =
|
||||
fa.iterator.foldLeft(z)(f)
|
||||
|
||||
override def foldRight[A, B](fa: FrontStack[A], z: => B)(f: (A, => B) => B) =
|
||||
fa.toBackStack.bqFoldRight(z)(
|
||||
(a, z) => f(a, z),
|
||||
(iaa, z) => iaa.foldRight(z)(f(_, _)),
|
||||
)
|
||||
|
||||
override def length[A](fa: FrontStack[A]) = fa.length
|
||||
}
|
||||
|
||||
implicit def `FrontStack Order`[A: Order]: Order[FrontStack[A]] = {
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
package com.daml.lf.data
|
||||
|
||||
import com.daml.scalautil.FoldableContravariant
|
||||
import com.daml.scalautil.Statement.discard
|
||||
|
||||
import ScalazEqual.{equalBy, orderBy, toIterableForScalazInstances}
|
||||
@ -393,6 +394,12 @@ object ImmArray extends ImmArrayInstances {
|
||||
}
|
||||
.map(_.toImmArray)
|
||||
}
|
||||
|
||||
override def foldLeft[A, B](fa: ImmArray[A], z: B)(f: (B, A) => B) =
|
||||
fa.foldLeft(z)(f)
|
||||
|
||||
override def foldRight[A, B](fa: ImmArray[A], z: => B)(f: (A, => B) => B) =
|
||||
fa.foldRight(z)(f(_, _))
|
||||
}
|
||||
|
||||
implicit def immArrayOrderInstance[A: Order]: Order[ImmArray[A]] = {
|
||||
@ -429,12 +436,13 @@ object ImmArray extends ImmArrayInstances {
|
||||
object ImmArraySeq extends ImmArraySeqCompanion {
|
||||
val Empty: ImmArraySeq[Nothing] = ImmArray.Empty.toSeq
|
||||
implicit val `immArraySeq Traverse instance`: Traverse[ImmArraySeq] = new Traverse[ImmArraySeq]
|
||||
with Foldable.FromFoldr[ImmArraySeq] {
|
||||
with Foldable.FromFoldr[ImmArraySeq]
|
||||
with FoldableContravariant[ImmArraySeq, ImmArray] {
|
||||
override def map[A, B](fa: ImmArraySeq[A])(f: A => B) = fa.toImmArray.map(f).toSeq
|
||||
override def foldLeft[A, B](fa: ImmArraySeq[A], z: B)(f: (B, A) => B) =
|
||||
fa.foldLeft(z)(f)
|
||||
override def foldRight[A, B](fa: ImmArraySeq[A], z: => B)(f: (A, => B) => B) =
|
||||
fa.foldRight(z)(f(_, _))
|
||||
|
||||
protected[this] override def Y = Foldable[ImmArray]
|
||||
protected[this] override def ctmap[A](xa: ImmArraySeq[A]) = xa.toImmArray
|
||||
|
||||
override def traverseImpl[F[_], A, B](
|
||||
immArr: ImmArraySeq[A]
|
||||
)(f: A => F[B])(implicit F: Applicative[F]): F[ImmArraySeq[B]] = {
|
||||
|
@ -75,6 +75,10 @@ class FrontStackSpec
|
||||
|
||||
"Traverse instance" should {
|
||||
checkLaws(ScalazProperties.traverse.laws[FrontStack])
|
||||
|
||||
"reconstruct itself with foldRight" in forAll { fs: FrontStack[Int] =>
|
||||
scalaz.Foldable[FrontStack].foldRight(fs, FrontStack.empty[Int])(_ +: _) should ===(fs)
|
||||
}
|
||||
}
|
||||
|
||||
"Equal instance" should {
|
||||
|
@ -0,0 +1,60 @@
|
||||
// Copyright (c) 2021 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml.scalautil
|
||||
|
||||
import scalaz.{Monoid, Foldable, Semigroup}
|
||||
import FoldableContravariant._
|
||||
|
||||
// Specialized overrides for when a Foldable wraps another Foldable.
|
||||
// If you need to hand-write some of these, just mix in the traits you
|
||||
// don't want to hand-write.
|
||||
private[daml] trait FoldableContravariant[X[_], Y[_]]
|
||||
extends CoreOps[X, Y]
|
||||
with Semigroupoids[X, Y]
|
||||
with Conversions[X, Y]
|
||||
with Lookups[X, Y]
|
||||
|
||||
private[daml] object FoldableContravariant {
|
||||
trait CtMap[X[_], Y[_]] {
|
||||
protected[this] def Y: Foldable[Y]
|
||||
protected[this] def ctmap[A](ax: X[A]): Y[A]
|
||||
}
|
||||
|
||||
// non-derived combinators
|
||||
trait CoreOps[X[_], Y[_]] extends Foldable[X] with CtMap[X, Y] {
|
||||
override final def foldLeft[A, B](xa: X[A], z: B)(f: (B, A) => B) = Y.foldLeft(ctmap(xa), z)(f)
|
||||
override final def foldRight[A, B](xa: X[A], z: => B)(f: (A, => B) => B) =
|
||||
Y.foldRight(ctmap(xa), z)(f)
|
||||
override final def foldMap[A, Z: Monoid](xa: X[A])(f: A => Z) = Y.foldMap(ctmap(xa))(f)
|
||||
}
|
||||
|
||||
// plays on functions from the semigroupoids library
|
||||
trait Semigroupoids[X[_], Y[_]] extends Foldable[X] with CtMap[X, Y] {
|
||||
override final def foldMapRight1Opt[A, B](xa: X[A])(z: A => B)(f: (A, => B) => B) =
|
||||
Y.foldMapRight1Opt(ctmap(xa))(z)(f)
|
||||
override final def foldMapLeft1Opt[A, B](xa: X[A])(z: A => B)(f: (B, A) => B) =
|
||||
Y.foldMapLeft1Opt(ctmap(xa))(z)(f)
|
||||
override final def foldMap1Opt[A, B: Semigroup](xa: X[A])(f: A => B) =
|
||||
Y.foldMap1Opt(ctmap(xa))(f)
|
||||
}
|
||||
|
||||
// to (collection type) converters
|
||||
trait Conversions[X[_], Y[_]] extends Foldable[X] with CtMap[X, Y] {
|
||||
override final def toStream[A](xa: X[A]) = Y.toStream(ctmap(xa))
|
||||
override final def toSet[A](xa: X[A]) = Y.toSet(ctmap(xa))
|
||||
override final def toList[A](xa: X[A]) = Y.toList(ctmap(xa))
|
||||
override final def toVector[A](xa: X[A]) = Y.toVector(ctmap(xa))
|
||||
override final def toIList[A](xa: X[A]) = Y.toIList(ctmap(xa))
|
||||
override final def toEphemeralStream[A](xa: X[A]) =
|
||||
Y.toEphemeralStream(ctmap(xa))
|
||||
}
|
||||
|
||||
// list-like operations
|
||||
trait Lookups[X[_], Y[_]] extends Foldable[X] with CtMap[X, Y] {
|
||||
override final def index[A](xa: X[A], i: Int) = Y.index(ctmap(xa), i)
|
||||
override final def length[A](xa: X[A]) = Y.length(ctmap(xa))
|
||||
override final def all[A](xa: X[A])(p: A => Boolean): Boolean = Y.all(ctmap(xa))(p)
|
||||
override final def any[A](xa: X[A])(p: A => Boolean): Boolean = Y.any(ctmap(xa))(p)
|
||||
}
|
||||
}
|
@ -6,10 +6,12 @@ package com.daml.scalautil.nonempty
|
||||
import scala.collection.compat._
|
||||
import scala.collection.{immutable => imm}, imm.Map, imm.Set
|
||||
import scalaz.Id.Id
|
||||
import scalaz.{Foldable, Foldable1, Monoid, OneAnd, Semigroup, Traverse}
|
||||
import scalaz.{Foldable, Foldable1, OneAnd, Semigroup, Traverse}
|
||||
import scalaz.Leibniz, Leibniz.===
|
||||
import scalaz.Liskov, Liskov.<~<
|
||||
import scalaz.syntax.std.option._
|
||||
|
||||
import com.daml.scalautil.FoldableContravariant
|
||||
import NonEmptyCollCompat._
|
||||
|
||||
/** The visible interface of [[NonEmpty]]; use that value to access
|
||||
@ -169,7 +171,7 @@ sealed abstract class NonEmptyCollInstances extends NonEmptyCollInstances0 {
|
||||
|
||||
sealed abstract class NonEmptyCollInstances0 {
|
||||
implicit def foldable1[F[_]](implicit F: Foldable[F]): Foldable1[NonEmptyF[F, *]] =
|
||||
NonEmpty.substF(new Foldable1[F] {
|
||||
NonEmpty.substF(new Foldable1[F] with FoldableContravariant[F, F] {
|
||||
private[this] def errEmpty(fa: F[_]) =
|
||||
throw new IllegalArgumentException(
|
||||
s"empty structure coerced to non-empty: $fa: ${fa.getClass.getSimpleName}"
|
||||
@ -187,12 +189,9 @@ sealed abstract class NonEmptyCollInstances0 {
|
||||
override def foldMapLeft1[A, B](fa: F[A])(z: A => B)(f: (B, A) => B) =
|
||||
assertNE(fa, F.foldMapLeft1Opt(fa)(z)(f))
|
||||
|
||||
override def foldMap[A, B: Monoid](fa: F[A])(f: A => B) = F.foldMap(fa)(f)
|
||||
protected[this] override def Y = F
|
||||
|
||||
override def foldRight[A, B](fa: F[A], z: => B)(f: (A, => B) => B) = F.foldRight(fa, z)(f)
|
||||
|
||||
override def foldLeft[A, B](fa: F[A], z: B)(f: (B, A) => B) =
|
||||
F.foldLeft(fa, z)(f)
|
||||
protected[this] override def ctmap[A](xa: F[A]) = xa
|
||||
})
|
||||
|
||||
import scala.language.implicitConversions
|
||||
|
Loading…
Reference in New Issue
Block a user