Effect handling and monad composition in c(x)
c(x)의 효과 처리와 모나드 조합
c(x)는 타입과 값에 같은 언어를 쓰고, 교집합·합집합 연산과 확장 가능한 has 메서드로 모나드 조합과 효과 처리를 표현합니다. 글쓴이는 서로 다른 모나드의 연산을 한 블록에서 이어 쓰는 예제와, 실행 시점에 핸들러를 적용해 효과 구현을 바꾸는 방식을 소개합니다.
- 주제
AI 요약
c(x) 개발자는 10년간 쉬었던 언어 작업을 다시 사이드 프로젝트로 이어가며, 현재 구현의 효과 처리와 모나드 조합 방식을 소개합니다. c(x)는 타입 수준 코드와 런타임 코드를 같은 언어로 작성합니다. 함수와 타입을 통합하고 런타임 값을 타입의 의존성으로 쓰는 정적 컴파일 언어입니다. 글쓴이는 런타임 입력을 확인해 제약을 증명하면 컴파일러가 타입 로직을 지울 수 있다고 설명합니다.
교집합과 합집합으로 표현하는 조합
글쓴이는 Haskell의 do 표기법처럼 여러 연산을 순서대로 쓰되, c(x)에서는 모나드 문맥의 여러 줄 블록이 자동으로 bind 호출의 연쇄로 바뀐다고 설명합니다. 일반적인 모나드는 다른 모나드와 쉽게 섞이지 않고, 모나드 변환기나 효과 라이브러리는 상호 변환을 위한 보일러플레이트와 추상화 부담을 낳는다고 지적합니다.
c(x)는 언어의 기본 연산인 교집합(&)과 합집합(||)을 조합에 활용합니다. ||는 먼저 왼쪽 타입과 교차해 보고 결과가 빈 집합이면 오른쪽을 시도합니다. 패턴 매칭도 이 연산으로 표현합니다. has 메서드는 객체에 필드나 함수를 확장해 붙이는 기능입니다. &로 인터페이스 조건과 구현을 합칠 수 있으며, 두 조건이 맞지 않으면 거부합니다. 뒤에 쓴 정의가 앞의 정의를 덮어쓰는 방식은 아닙니다. 같은 이름의 메서드도 조건을 조합할 수 있고, ||는 정수와 실수 입력에 따라 다른 오버로딩을 선택하는 데 쓰입니다.
모나드와 서로 다른 문맥
글은 Option과 Throw를 예로 듭니다. Option은 값이 있거나 none이며, Throw는 정상 결과나 예외 메시지를 담습니다. 각각 returnOf와 bindOf를 정의하면 <-로 연산을 이어갈 수 있습니다. 일반적인 bind 형식은 f a -> (a -> f b) -> f b라서 같은 모나드 안의 연쇄를 전제합니다. 하지만 예제에서는 getOdd가 Option Int를, checkPositive가 Throw Int를 반환합니다.
글쓴이는 서로 다른 모나드의 연산을 잇기 위해 결과 타입을 열어 둔 bindOf 구현을 사용합니다. 각 <-가 적용 가능한 bind를 선택하고, 마지막에는 returnOf (Throw || Option)으로 결과 문맥을 명시합니다. 일반화한 bind는 f1 a -> (a -> f2 b) -> f3 b 형태이며, 이 방식은 polymonad 연구와 닮았지만 c(x)의 형식화가 수학적으로 증명된 것은 아니라고 선을 긋습니다. c(x)에서는 보통의 모나드 bind를 사용하고, 언어의 선택 과정이 더 복잡한 역할을 합니다. 글쓴이는 이를 정식화하는 일을 현재 우선순위로 두지 않습니다.
외부 핸들러로 구현을 선택하는 효과
효과는 연산의 인터페이스를 먼저 정의하고, 구체적인 동작은 핸들러가 제공하는 구조로 소개합니다. Throw 인터페이스에 throwOf의 계약만 선언하면 프로그램은 예외를 실제로 어떻게 만들지 정하지 않습니다. 이후 핸들러가 throwOf를 일반 예외나 접두어를 붙인 예외로 구현합니다. 같은 프로그램에 서로 다른 핸들러를 적용하면 결과 메시지가 달라집니다. 핸들러는 프로그램 바깥에서 적용하며, 런타임에도 선택할 수 있습니다. 핸들러가 적용되면 해당 호출의 함수·계산 타입이 정제되고, 정제 결과가 구현이 비어 있는 연산의 수신자까지 전파됩니다.
글쓴이는 효과 문법을 별도로 늘리지 않고 has 메서드, 집합 연산, 부분 항등 함수와 술어로 표현하는 방향을 택했습니다. 조합이 예상대로 동작하는지 계속 시험하고 있으며, 중요한 부분은 Lean으로 검증했다고 덧붙입니다.
Reddit 반응
- @u/AustinVelonaut — 흥미로워 보입니다! 모나드, 효과, 함수 오버로딩 등을 통합하면서 서로 다른 모나드를 섞은 do 블록도 자동으로 처리하려는 시도가 있군요. c(x)에 관한 정보가 더 있나요?
- @u/Rasie1 — 고맙습니다! 네, 새로운 시도라고 생각합니다. 정제 기능을 가능하게 하는 가장 근본적인 부분은 아직 보여드리지 않았습니다. 제 X 계정에 스크린샷을 많이 올립니다. 곧 c(x)에 관한 더 구체적인 자료도 만들겠습니다.
- @u/particlemanwavegirl — 흥미롭습니다. 아직 다 읽지는 않았지만,
throw라는 키워드에는 이 개념이 굳이 짊어질 필요 없는 의미가 많이 따라붙는다고 생각합니다. 왜 그 이름을 골랐나요?- @u/Rasie1 — 실행을 이어가거나 오류 메시지와 함께 예외를 반환하는 모나드 연쇄를 보여주는 예제입니다. 키워드가 아니라 그 자리에서 정의한 새 식별자이며, 이해하기 쉬운 예로
throw를 골랐습니다.
- @u/Rasie1 — 실행을 이어가거나 오류 메시지와 함께 예외를 반환하는 모나드 연쇄를 보여주는 예제입니다. 키워드가 아니라 그 자리에서 정의한 새 식별자이며, 이해하기 쉬운 예로
원문: kvachev.com / 번역·요약: Trawling