반디북
객체에서 함수로
Ch9
우석

연습문제 9.1

@Test
fun `왼쪽 항등원 법칙`() {
    val initialValue = Random.nextInt()
    val f: (Int) -> ContextReader<Int, Int> = { x -> ContextReader { it * 2 } }
    val initialMonad = ContextReader { _: Int -> initialValue }
    expectThat(initialMonad.bind(f).runWith(2)).isEqualTo(f(initialValue).runWith(2))
}
 
@Test
fun `오른쪽 항등원 법칙`() {
    val initialValue = Random.nextInt()
    val initialMonad = ContextReader { _: Int -> initialValue }
    val identity: (Int) -> ContextReader<Int, Int> = { value -> ContextReader { value } }
    val initialMonadWithIdentity = initialMonad.bind(identity)
 
    assert(initialMonad.runWith(1) == initialMonadWithIdentity.runWith(1))
}
 
@Test
fun `결합 법칙`() {
    val initialValue = Random.nextInt()
 
    val f: (Int) -> ContextReader<Int, Int> = { x -> ContextReader { it + x } }
    val g: (Int) -> ContextReader<Int, Int> = { ContextReader { it * 2 } }
 
    val left = ContextReader { _: Int -> initialValue }.bind(f).bind(g)
    val right = ContextReader { _: Int -> initialValue }.bind { x -> f(x).bind(g) }
 
    assert(left.runWith(3) == right.runWith(3))
}

연습문제 9.2

fun <CTX, T> ContextReader<CTX, ContextReader<CTX, T>>.join(): ContextReader<CTX, T> = ContextReader { ctx -> this.runWith(ctx).runWith(ctx) }
 
fun <U> bind(f: (T) -> ContextReader<CTX, U>): ContextReader<CTX, U> = this.transform(f).join()
만혁

연습문제 9.1

private val f: (Int) -> ContextReader<Int, Int> = { x -> ContextReader { ctx -> x * 2 } }
    private val g: (Int) -> ContextReader<Int, Int> = { y -> ContextReader { ctx -> y + 10 } }
 
    @Test
    fun `Left Identity Law`() {
        val random = Random.nextInt()
        val value = 5
 
        val init = ContextReader { ctx: Int -> random }
        val left = init.bind(f).runWith(value)
        val right = f(value).runWith(value)
 
        println("Left Identity: $left == $right")
    }
 
    @Test
    fun `Right Identity Law`() {
        val random = Random.nextInt(10)
        val value = 5
 
        val reader = ContextReader { _: Int -> 10 + random }
        val right = reader.runWith(value)
        val left = reader.bind { x -> ContextReader { _: Int -> x } }.runWith(value)
 
        println("Right Identity: $left == $right")
 
    }
 
    @Test
    fun `ContextReader Associativity Law`() {
        val random = Random.nextInt(10)
        val value = 5
 
        val reader = ContextReader { _: Int -> 3 + random } // 3 + 12 = 15
 
        val left = reader.bind(f).bind(g).runWith(value)
        val right = reader.bind { value -> f(value).bind(g) }.runWith(value)
 
        println("Associativity: $left == $right")
    }

연습문제 9.2

fun <CTX, T> ContextReader<CTX, ContextReader<CTX, T>>.join(): ContextReader<CTX, T>
 = ContextReader { ctx -> this.runWith(ctx).runWith(ctx) }
 
 
fun <CTX, T, U> ContextReader<CTX, T>.bind(
    f: (T) -> ContextReader<CTX, U>
): ContextReader<CTX, U> = this.transform(f).join()