Skip to content

Instantly share code, notes, and snippets.

@calvinlfer
Created November 30, 2016 17:26
Show Gist options
  • Save calvinlfer/9eda58150e095deeb42f922352783052 to your computer and use it in GitHub Desktop.
Save calvinlfer/9eda58150e095deeb42f922352783052 to your computer and use it in GitHub Desktop.
Factorial using the State monad
import cats.data.State
import cats.data.State._
def factorialWithState(x: Int): Int = {
def stateFactorial: State[Int, Int] =
get.flatMap(x =>
if (x <= 1)
State.pure(1)
else {
set[Int](x - 1).flatMap(_ => stateFactorial.map(z => x * z))
}
)
// return value in (State, Value)
stateFactorial.run(x).value._2
}
@calvinlfer
Copy link
Author

calvinlfer commented Nov 30, 2016

Written with @nbenns
Essentially translated the Haskell implementation here

In Haskell, >> is a flatMap that drops the input so flatMap(_ => ...)

@calvinlfer
Copy link
Author

calvinlfer commented Nov 30, 2016

With comments:

import cats.data.State
import State._

def factorialWithState(x: Int): Int = {
  def stateFactorial: State[Int, Int] =
    // get accesses the State and places it in the User Value
    // in (State, User Value)
    get.flatMap(x =>
      // x is the User Value
      if (x <= 1)
        State.pure(1)
      else {
        // set the State in (State, User Value)
        set[Int](x - 1)
          .flatMap(_ => 
            // return a State that will compute the next iteration
            // stateFactorial's z is the User Value
            // what is the User Value? Look at stateFactorial
            // it calls get which access the State in (State, User Value)
            // and places that in User Value
            stateFactorial.map(z => x * z)
          )
      }
    )
  // return value in (State, Value)
  stateFactorial.run(x).value._2
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment