Skip to content

Instantly share code, notes, and snippets.

@debasishg
Created December 11, 2010 16:11
Show Gist options
  • Save debasishg/737442 to your computer and use it in GitHub Desktop.
Save debasishg/737442 to your computer and use it in GitHub Desktop.
Intuitively, the (>=) :: m a → (a → m b) → m b of some Monad m allows the value returned by one computation to influence
the choice of another, whereas <*> the structure of a computation fixed, just sequencing the effects.
scala> def ev(i: Int) = {println("in ev"); if (i % 2 == 0) Some(i) else None;}
ev: (i: Int)Option[Int]
scala> def div5(i: Int) = {println("in div5"); if (i % 5 == 0) Some(i/5) else None;}
div5: (i: Int)Option[Int]
scala> def div3(i: Int) = {println("in div3"); if (i % 3 == 0) Some(i/3) else None;}
div3: (i: Int)Option[Int]
scala> val mc = ((_: Int) * (_: Int) * (_: Int)).curried
mc: (Int) => (Int) => (Int) => Int = <function1>
scala> (ev(12) <*> (ev(14) <*> (ev(18) map mc)))
in ev
in ev
in ev
res1: Option[Int] = Some(3024)
// bails out from ev(13) but sequences all side-effects
scala> (ev(12) <*> (ev(13) <*> (ev(18) map mc)))
in ev
in ev
in ev
res2: Option[Int] = None
scala> (some(150) ∗ div5 ∗ div3 ∗ div5)
in div5
in div3
in div5
res6: Option[Int] = Some(2)
// bails out from div3 and does not execute the side-effect of the last div5
// structure of computation changes
scala> (some(50) ∗ div5 ∗ div3 ∗ div5)
in div5
in div3
res7: Option[Int] = None
scala> val ifA = (b: Boolean) => (t: Int) => (f: Int) => (if (b) t else f)
ifA: (Boolean) => (Int) => (Int) => Int = <function1>
scala> none <*> (some(12) <*> (some(false) map ifA))
res41: Option[Int] = None
// bad!
scala> none <*> (some(12) <*> (some(true) map ifA))
res42: Option[Int] = None
// good!
scala> true.some ifM(none[Int], 1.some)
res43: Option[Int] = None
// good!
scala> false.some ifM(none[Int], 1.some)
res44: Option[Int] = Some(1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment