swap :: State a (State a ()) 같은 함수를 algebraic effect로 기술하려면 같은 효과가 두번 나오기에 koka는 named handlers를 실험하고 있다. 옳은 방향이라고 생각한다. 기존에 koka는 masked effect라는 복잡한 개념을 사용해 outer effect에 접근했다.

fun swap-with-mask() : <state<a>, state<a>> () {
  val inner-val = get() // innermost
  val outer-val = mask<state<a>> { get() } // skip the innermost
  set(outer-val) // innermost
  mask<state<a>> { set(inner-val) } // skip the innermost
}

하지만 named handler와 함께라면 이렇게 쓸 수 있다

fun swap-with-named-handlers(h1, h2) : <state<a>> () {
  val val1 = perform get() at h1
  val val2 = perform get() at h2
  perform set(val2) at h1
  perform set(val1) at h2
}

seealso: https://dl.acm.org/doi/10.1145/3563289

1

If you have a fediverse account, you can reply to this note from your own instance. Search https://hackers.pub/ap/notes/019a271d-a26e-74b3-b527-3625476c1ee2 on your instance and reply to it.

(위 트윗의 koka 코드도 그렇고 이 트윗의 effekt 코드도 그렇고 귀찮아서 대충 Gemini 시켰다. 틀려도 양해 바란다)

반면 Effekt의 Capability Passing Style 멘탈 모델로 생각하면 약간 양상이 달라지는데, Capability는 값 주입의 관점으로 보기 때문에 Effect를 it happens가 아니라 it requires로 본다. 그래서 named handler 같은 코드를 이렇게 쓴다. 걍 computation을 받는 함수인 것.

fun swap[A]() {h1: State[A]} {h2: State[A]}: Unit = {
  val a = h1.get();
  val b = h2.get();
  h1.set(a);
  h2.set(b);
}

koka는 happens지만 effekt는 requires다. 하지만 named handler에서는 둘 다 그냥 computation을 인자로 넘기는 모양새에 수렴했다.

2