Skip to content

Commit

Permalink
Add new laws
Browse files Browse the repository at this point in the history
  • Loading branch information
kubukoz committed Jul 31, 2019
1 parent ad7be92 commit 911a30f
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 9 deletions.
21 changes: 17 additions & 4 deletions core/src/main/scala/cats/mtl/MonadState.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,11 @@ package mtl
*
* MonadState has four external laws:
* {{{
*
* def getThenSetDoesNothing = {
* get >>= set <-> pure(())
* }
* def setThenGetReturnsSetted(s: S) = {
* def setThenGetReturnsSet(s: S) = {
* set(s) *> get <-> set(s) *> pure(s)
* }
* def setThenSetSetsLast(s1: S, s2: S) = {
Expand All @@ -21,14 +22,26 @@ package mtl
* }
* }}}
*
* `MonadState` has two internal law:
* `MonadState` has five internal laws:
* {{{
* def modifyIsGetThenSet(f: S => S) = {
* modify(f) <-> (inspect(f) flatMap set)
* }
*
* def inspectLaw[A](f: S => A) = {
* inspect(f) <-> (get map f)
* def setIsStateUnit(s: S) = {
* set(s) <-> state(_ => (s, ()))
* }
* def inpectIsState[A](f: S => A) = {
* inspect(f) <-> state(s => (s, f(s)))
* }
*
* def modifyIsState(f: S => S) = {
* modify(f) <-> state(s => (f(s), ()))
* }
*
* def stateIsGetAndModify[A](f: S => (S, A)) = {
* state(f) <-> (get.map(old => f(old)._2) <* modify(old => f(old)._1))
* }
* }}}
*
Expand Down
20 changes: 18 additions & 2 deletions laws/src/main/scala/cats/mtl/laws/MonadStateLaws.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ trait MonadStateLaws[F[_], S] {
(get >>= set) <-> pure(())
}

def setThenGetReturnsSetted(s: S): IsEq[F[S]] = {
def setThenGetReturnsSet(s: S): IsEq[F[S]] = {
(set(s) *> get) <-> (set(s) *> pure(s))
}

Expand All @@ -32,10 +32,26 @@ trait MonadStateLaws[F[_], S] {
get *> get <-> get
}

// internal law:
// internal laws:
def modifyIsGetThenSet(f: S => S): IsEq[F[Unit]] = {
modify(f) <-> ((get map f) flatMap set)
}

def setIsStateUnit(s: S): IsEq[F[Unit]] = {
set(s) <-> state(_ => (s, ()))
}

def inpectIsState[A](f: S => A): IsEq[F[A]] = {
inspect(f) <-> state(s => (s, f(s)))
}

def modifyIsState(f: S => S): IsEq[F[Unit]] = {
modify(f) <-> state(s => (f(s), ()))
}

def stateIsGetAndModify[A](f: S => (S, A)): IsEq[F[A]] = {
state(f) <-> (get.map(old => f(old)._2) <* modify(old => f(old)._1))
}
}

object MonadStateLaws {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,21 @@ trait MonadStateTests[F[_], S] extends Laws {
ArbS: Arbitrary[S],
CogenS: Cogen[S],
EqFU: Eq[F[Unit]],
EqFS: Eq[F[S]]
EqFS: Eq[F[S]],
EqFA: Eq[F[A]]
): RuleSet = {
new DefaultRuleSet(
name = "monadState",
parent = None,
"get then set has does nothing" -> laws.getThenSetDoesNothing,
"set then get returns the setted value" -> ∀(laws.setThenGetReturnsSetted _),
"set then get returns the set value" -> ∀(laws.setThenGetReturnsSet _),
"set then set sets the last value" -> ∀(laws.setThenSetSetsLast _),
"get then get gets once" -> laws.getThenGetGetsOnce,
"modify is get then set" -> ∀(laws.modifyIsGetThenSet _)
"modify is get then set" -> ∀(laws.modifyIsGetThenSet _),
"set is state(unit)" -> ∀(laws.setIsStateUnit _),
"inspect is state" -> ∀(laws.inpectIsState[A] _),
"modify is state" -> ∀(laws.modifyIsState _),
"stateIsGetAndModify" -> ∀(laws.stateIsGetAndModify[A] _)
)
}

Expand Down

0 comments on commit 911a30f

Please sign in to comment.