Skip to content

Instantly share code, notes, and snippets.

@hikaMaeng
Created April 23, 2025 14:29
Show Gist options
  • Save hikaMaeng/1b073b08c327ff72d9402e307218df24 to your computer and use it in GitHub Desktop.
Save hikaMaeng/1b073b08c327ff72d9402e307218df24 to your computer and use it in GitHub Desktop.
data class Holder<T>(private val value:T){
companion object{
fun <T, R> lift(block:(T)->R):(Holder<T>)->Holder<R> = {it.map(block)}
}
fun <R> map(block:(T)->R):Holder<R> = Holder(block(value))
fun combine(other:Holder<T>, block:(T, T)->T):Holder<T> = map{ block(it, other.value) }
}
/*
map은 XXX만 주면 Holder생성함
combine이 map의 비위만 맞춰주면 생성자 코드를 중복으로 쓰지 않겠지?
펑터는 map을 갖고 있다
모나드는 flatmap갖고 있다
어플리커티브는 map2갖고 있다
폴더블 은 fold를 갖고 있다
반군 결합법칙 요구
실제 계산 전에 계산경로를 선언한다 ->DSL로 가는 길
종결함수
지연계산
결합법칙
합성 -> 최적화
*/
import org.example.b
sealed interface Outcome<out ERROR, out VALUE>{
fun <VALUE2> mapValue(block:(VALUE)->VALUE2):Outcome<ERROR, VALUE2> = when(this){
is Success -> Success(block(value))
is Failure -> this
}
fun <ERROR2> mapError(block:(ERROR)->ERROR2):Outcome<ERROR2, VALUE> = when(this){
is Success -> this
is Failure -> Failure(block(error))
}
}
data class Success<T>(val value:T):Outcome<Nothing, T>
data class Failure<E>(val error:E):Outcome<E, Nothing>
/*
val a:Outcome<Any, Any> = Outcome<Int, Int>
val a:Outcome<String, Int> = Success(3):Outcome<Nothing, Int>
모든 클래스의 부모 : object, any 어떤 타입이 와도 대체가능성 top upper bound
val a:Any = 어떤타입이 와도 성립
모든 클래스의 자식 : nothing - 원래 타입이 뭐라도 nothing에게는 부모다
val a:Int = Nothing 개념상 모든 타입의 자식이라니 코드가 성립하는건 알겠다
이 밑으로는 실행하지 않겠어 = Nothing타입이 나오면 무조건 throw가 일어난다 런타임에서는
컴파일타임에는 문제없이 컴파일 됨
fun a():Int{throw ThrowException()}
val a:String = Nothing
*/
//inline fun <ERROR, VALUE> Outcome<ERROR, VALUE>.onSuccess(block:(VALUE)->Nothing):ERROR = when(this){
// is Success -> block(value)
// is Failure -> error
//}
//inline fun <ERROR, VALUE> Outcome<ERROR, VALUE>.onFailure(block:(ERROR)->Nothing):VALUE = when(this){
// is Success -> value
// is Failure -> block(error)
//}
fun q7_2(){
val a:Outcome<Int, Int> = Success(3)
val piped = a.mapValue { it + 1 }.mapError { "aaa" }.mapValue { it.toDouble() } //연산계획 pipeline - 결합법칙과 합성을 요구
piped.onFailure { //터미널 연산
println("error: $it")
}?.let{
println("value: $it")
}
piped.onSuccess {
println("value: $it")
}?.let{
println("error: $it")
}
val result = piped.recover {
//니가 어떤 io에러나 통신에러를 뱉어도 난 무조건 이상없이 이후 논리가 전개되는 값을 줄수 있어
0.0
}
// result로 뭘 해도 문제없음
//여기서부터는 실행되지 않음 block이 호출되면 q7_2를 탈출함
}
inline fun <ERROR, VALUE> Outcome<ERROR, VALUE>.onSuccess(block:(VALUE)->Unit):ERROR? = when(this){
is Success -> {
block(value)
null
}
is Failure -> error
}
inline fun <ERROR, VALUE> Outcome<ERROR, VALUE>.onFailure(block:(ERROR)->Unit):VALUE? = when(this){
is Success -> value
is Failure -> {
block(error)
null
}
}
inline fun <ERROR, VALUE> Outcome<ERROR, VALUE>.recover(block:(ERROR)->VALUE):VALUE = when(this){
is Success -> value
is Failure -> block(error)
}
sealed class Outcome2<out ERROR, out VALUE>(val value:Any){
companion object{
fun <T:Any> runTry(block:()->T):Outcome2<Throwable, T> = try{
Success(block())
}catch (e:Throwable){
Failure(e)
}
}
class Success<T:Any>(value:T):Outcome2<Nothing, T>(value as Any)
class Failure<E:Throwable>(error:E):Outcome2<E, Nothing>(error as Any)
fun <VALUE2:Any> map(block:(VALUE)->VALUE2):Outcome2<ERROR, VALUE2> = when(this){
is Success -> Success(block(value as VALUE))
is Failure -> this
}
fun <ERROR2:Throwable> mapError(block:(ERROR)->ERROR2):Outcome2<ERROR2, VALUE> = when(this){
is Success -> this
is Failure -> Failure(block(value as ERROR))
}
inline fun onSuccess(block:(VALUE)->Unit):ERROR? = when(this){
is Success-> {
block(value as VALUE)
null
}
is Failure-> value as ERROR
}
inline fun onFailure(block:(ERROR)->Unit):VALUE? = when(this){
is Success-> value as VALUE
is Failure-> {
block(value as ERROR)
null
}
}
}
inline fun <ERROR, VALUE> Outcome2<ERROR, VALUE>.recover(block:(ERROR)->VALUE):VALUE = when(this){
is Outcome2.Success-> value as VALUE
is Outcome2.Failure-> block(value as ERROR)
}
package org.example
fun Long.isOdd():Boolean = this % 2L == 1L
fun longSeq(start:Long, end:Long) = sequence {
var i = start
while (i <= end) {
yield(i)
i += 1L
}
}
/*
연산과 메모리를 교환할 수 있다
중학교 2학년 수학 교과서 부록편에는 sin표 (메모리)
내가 sin을 계산(연산 = 함수 = 함수형프로그래밍이란 메모리(상태)를 연산으로 표현하는 것
지연연산 그때까지 계산하지 않겠어)으로 얻을 수도 있지만 sin표를 보고도 같은 값을 얻을 수 있다. = 결과는 동일
*/
fun LongRange.toLongSeq() = longSeq(this.first, this.last)
private tailrec fun <T> clone(list:List<T>, cursor:Int, acc:List<T>):List<T>
= if(cursor == list.size) acc else clone(list, cursor + 1, acc + list[cursor])
fun <T> List<T>.dropFirst():List<T> = if(isEmpty()) this else clone(this, 1, emptyList())
fun <T> List<T>.head():Pair<T?, List<T>> = firstOrNull() to dropFirst()
private tailrec fun <T> printLoop(list:List<T>){
val (head, tail) = list.head()
if(head == null) return
else {
println(head)
printLoop(tail)
}
}
fun <T> List<T>.printAll() = printLoop(this)
fun q8_1(){
val a = (1L..10L).toLongSeq().filter{ it.isOdd() }.map{ it * 2L }
val b = a.sum()
listOf(1,2,3,4,5).printAll()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment