만혁
연습문제 7.1
data class Holder<T>(private val value: T) {
fun<U> transform(f: (T) -> U): Holder<U> = Holder(f(value))
fun combine(other: Holder<T>, f: (T, T) -> T): Holder<T> {
return Holder(f(this.value, other.value))
}
fun combine2(other: Holder<T>, f: (T, T) -> T): Holder<T> {
return this.transform { it -> f(it, other.value) }
}
@Test
fun test() {
val hello = Holder("Hello")
val world = Holder("World")
val result = hello.combine(world) {first, second -> "$first $second"}
Assertions.assertEquals(result, Holder("Hello World"))
}
}
연습문제 7.3
fun <T> T.asSuccess(): Outcome<Nothing, T> = Success(this)
fun <E : OutcomeError> E.asFailure(): Outcome<E, Nothing> = Failure(this)
sealed class Outcome<out E : OutcomeError, out T> {
fun <U> transform(f: (T) -> U): Outcome<E, U> =
when (this) {
is Success -> f(value).asSuccess()
is Failure -> this
}
fun <F : OutcomeError> transformFailure(f: (E) -> F): Outcome<F, T> =
when (this) {
is Success -> this
is Failure -> f(error).asFailure()
}
}
연습문제 7.4
fun <T> tryAndCatch(f: () -> T): Outcome<ThrowableError, T> {
return try {
f().asSuccess()
} catch (t: Throwable) {
ThrowableError(t).asFailure()
}
}
우석
연습문제 7.1
fun combine(other: Holder<T>, f: (T, T) -> T): Holder<T> =
transform { v -> f(v, other.value) }
연습문제 7.2
@Test
fun 펑터는_항등사상을_보존해야_한다() {
repeat(1000) {
val randomNumber = random.nextInt().asSuccess()
val sut = randomNumber.transform(::identity)
expectThat(randomNumber).isEqualTo(sut)
}
}
@Test
fun 펑터는_사상의_합성을_보존해야_한다() {
repeat(1000) {
val randomString = getRandomString(random.nextInt(1000)).asSuccess()
val o1 = randomString.transform {
v -> v.length
}.transform {
v -> v + 1
}
val lengthPlusOne = String::length andThen Int::inc
val o2 = randomString.transform(lengthPlusOne)
expectThat(o1).isEqualTo(o2)
}
}
fun getRandomString(length: Int): String {
val allowedChars = ('A'..'Z') + ('a'..'z') + ('0'..'9')
return (1..length)
.map { allowedChars.random() }
.joinToString("")
}
연습문제 7.3
fun <F : OutcomeError> transformFailure(f: (E) -> F): Outcome<F, T> =
when (this) {
is Failure -> f(this.error).asFailure()
is Success -> this
}
연습문제 7.4
fun <T> tryAndCatch(block: () -> T): Outcome<ThrowableError, T> {
return try {
block().asSuccess()
} catch (t: Throwable) {
ThrowableError(t).asFailure()
}
}