Skip to content

Commit

Permalink
Merge pull request #482 from daron666/suspend-vars-in-synclaws
Browse files Browse the repository at this point in the history
Suspend vars in SyncLaws
  • Loading branch information
alexandru authored Feb 11, 2019
2 parents cfc0ca5 + 0a882ac commit c740c25
Showing 1 changed file with 14 additions and 12 deletions.
26 changes: 14 additions & 12 deletions laws/shared/src/main/scala/cats/effect/laws/SyncLaws.scala
Original file line number Diff line number Diff line change
Expand Up @@ -36,47 +36,49 @@ trait SyncLaws[F[_]] extends BracketLaws[F, Throwable] with DeferLaws[F] {
def suspendThrowIsRaiseError[A](e: Throwable) =
F.suspend[A](throw e) <-> F.raiseError(e)

def unsequencedDelayIsNoop[A](a: A, f: A => A) = {
def unsequencedDelayIsNoop[A](a: A, f: A => A) = F.suspend {
var cur = a
val change = F delay { cur = f(cur) }
val _ = change

F.delay(cur) <-> F.pure(a)
}
F.delay(cur)
} <-> F.pure(a)

def repeatedSyncEvaluationNotMemoized[A](a: A, f: A => A) = {
def repeatedSyncEvaluationNotMemoized[A](a: A, f: A => A) = F.suspend {
var cur = a
val change = F delay { cur = f(cur) }
val read = F.delay(cur)

change *> change *> read <-> F.pure(f(f(a)))
}
change *> change *> read
} <-> F.pure(f(f(a)))


def propagateErrorsThroughBindSuspend[A](t: Throwable) = {
val fa = F.delay[A](throw t).flatMap(x => F.pure(x))

fa <-> F.raiseError(t)
}

def bindSuspendsEvaluation[A](fa: F[A], a1: A, f: (A, A) => A) = {
def bindSuspendsEvaluation[A](fa: F[A], a1: A, f: (A, A) => A) = F.suspend {
var state = a1
val evolve = F.flatMap(fa) { a2 =>
state = f(a1, a2)
F.pure(state)
}
// Observing `state` before and after `evolve`
F.map2(F.pure(state), evolve)(f) <-> F.map(fa)(a2 => f(a1, f(a1, a2)))
}
F.map2(F.pure(state), evolve)(f)
} <-> F.map(fa)(a2 => f(a1, f(a1, a2)))


def mapSuspendsEvaluation[A](fa: F[A], a1: A, f: (A, A) => A) = {
def mapSuspendsEvaluation[A](fa: F[A], a1: A, f: (A, A) => A) = F.suspend {
var state = a1
val evolve = F.map(fa) { a2 =>
state = f(a1, a2)
state
}
// Observing `state` before and after `evolve`
F.map2(F.pure(state), evolve)(f) <-> F.map(fa)(a2 => f(a1, f(a1, a2)))
}
F.map2(F.pure(state), evolve)(f)
} <-> F.map(fa)(a2 => f(a1, f(a1, a2)))

def stackSafetyOnRepeatedLeftBinds(iterations: Int) = {
val result = (0 until iterations).foldLeft(F.delay(())) { (acc, _) =>
Expand Down

0 comments on commit c740c25

Please sign in to comment.