Well-Typed가 GHC, Cabal, HLS 및 핵심 해스켈 툴체인 전반에서 2025년 9월부터 11월까지 수행한 작업을 정리한 스물아홉 번째 해스켈 생태계 활동 보고서입니다.
URL: https://www.well-typed.com/blog/2025/12/haskell-ecosystem-report-september-november-2025/
이 글은 Well-Typed가 GHC, Cabal, HLS 및 핵심 해스켈 툴체인의 다른 구성 요소들에서 수행하고 있는 작업을 설명하는 해스켈 생태계 활동 보고서의 스물아홉 번째 판입니다. 이번 판은 대략 2025년 9월부터 2025년 11월까지의 기간을 다룹니다.
이전 판들은 haskell-ecosystem-report 태그에서 모아볼 수 있습니다.
Well-Typed는 상용 사용자가 Well-Typed 전문가의 지원을 받는 동시에, 이 보고서에 설명된 작업을 포함하여 해스켈 커뮤니티와 기술 생태계에 투자할 수 있도록 Haskell Ecosystem Support Packages를 제공합니다. 자세한 내용은 Haskell Foundation과의 파트너십으로 공개한 패키지 발표 글을 읽어보세요. 이 필수적인 유지보수 작업을 계속하기 위해서는 재원이 필요합니다!
해스켈 생태계 서포터인 Standard Chartered, Channable, QBayLogic에 큰 감사를 드립니다. 또한 이 작업이 가능하도록 기여해 주는 다른 고객사인 Anduril, Juspay, Mercury에도 감사드립니다. 마지막으로 HLS 릴리스 관리를 지원해 주는 HLS Open Collective에도 감사드립니다.
오랫동안 GHC의 핵심 메인터이너였던 Ben은 10월에 새 역할로 이동한다고 발표했습니다. 이 역할은 GHC 작업에 쓸 수 있는 시간이 줄어들겠지만, 그는 Well-Typed의 파트너로 남습니다. 또한 우리는 11월에 Magnus를 팀에 맞이하게 되어 기뻤습니다.
현재 Well-Typed의 해스켈 툴체인 팀은 다음과 같습니다:
또한 Well-Typed 내부의 많은 다른 구성원들도 가끔 GHC, Cabal, HLS에 기여하거나, 다른 오픈소스 해스켈 라이브러리 및 도구에 기여합니다. 이번 보고서에는 특히 Alex Washburn, Tobias Dammers, Wen Kokke, Wolfgang Jeltsch의 기여가 포함되어 있습니다.
Matthew는 base 라이브러리를 재설치 가능하게 만들어 GHC 업그레이드와 라이브러리 버전 업그레이드 간 결합도를 낮추기 위한 계획에 대해 커뮤니티 논의를 촉진해 왔습니다. 이 논의는 프로젝트에 대한 합의가 무엇인지 평가하고, 모든 이해관계자 사이에서 공동의 계획을 수립하는 것을 목표로 합니다.
Wolfgang과 Tobias는 재설치 가능한 base의 기술적 측면을 조사하고 있습니다. 예를 들어 여러 GHC 버전에서 API가 동일한 base를 실제로 어떻게 컴파일하는지, 외부 base 저장소의 테스트 체계는 어떻게 되는지, ghc-internal의 어떤 부분을 base로 다시 옮길 수 있는지 등의 질문을 다룹니다.
Sam은 해결되지 않은 HasField 제약에 대한 오류 메시지 힌트를 추가했습니다. 이제 GHC는 HasField fld_name rec_ty fld_ty 형태의 해결되지 않은 제약에 대해, 예를 들어 철자가 틀린 필드명에 대한 유사 이름 제안, 존재 타입(existentials)이나 forall을 포함하는 레코드 필드에 대한 경고, import 제안 등을 추가로 제공합니다. 이는 특히 OverloadedRecordDot 확장 사용자에게 유용합니다 (#18776, #22382, #26480, !14952).
Magnus는 ExplicitLevelImports 초기 구현에서 놓친 여러 사항을 수정했습니다. 예를 들어 잘못 제거된 레벨 검사를 다시 도입(#26099, !15053)하고, 모듈 그래프 이슈를 해결했습니다 (#26568, !15118). 또한 이 영역의 코드베이스 문서화도 개선했습니다 (!15117).
Sam은 보이지 않는 구성요소(invisible components)가 포함된 오류 메시지(예: Proxy @k ty의 k, 또는 TYPE r에서의 RuntimeRep 변수)가 보고되는 방식을 재정비했습니다. 이 과정에서 LinearTypes의 다중성(multiplicity) pretty-printing을 다른 보이지 않는 구성요소들과 일관되게 맞췄습니다 (#26335, #26340, !14761).
Sam은 불가능한(unsoluble) 제약을 계산할 때 TypeError msg를 추출하는 방식의 코드를 정리했습니다. 이로 인해 코드가 훨씬 더 일관되게 되었고, #26400에서처럼 중복 패턴 매치의 탐지도 개선되었습니다 (!14802).
Ben은 모듈을 하나도 포함하지 않는 패키지에 대해 GHC가 “unused package” 경고를 내지 않도록 특수 처리를 추가했습니다. 이러한 패키지는 보통 링커 플래그 제공 등 다른 목적에 쓰이기 때문입니다 (#24120, !14965).
Sam은 GHC 제안 #581의 type .. 및 data .. 네임스페이스 지정 와일드카드 구현 작업을 Vladislav Zavialov이 진행한 것을 리뷰했습니다 (!15014).
Sam은 패턴 매치 체커를 실행할 때 GHC가 타입체커 플러그인을 호출하도록 만들었습니다. 이는 타입체커 플러그인을 사용하면서 자연수를 포함하는 GADT(예: Vec :: Nat -> Type -> Type)를 다룰 때 패턴 매치 경고를 크게 개선합니다 (#26395, !14797).
Sam은 ghc 라이브러리에 Outputable Natural 인스턴스를 추가했습니다. 특히 자연수를 다루는 타입체커 플러그인에 유용합니다.
Sam은 인자의 표현(representation)이 타입 패밀리 환원 아래 숨겨져 있는 함수 적용(예: #26072)을 허용하도록 표현 다형성 검사를 개선했습니다. 이 작업의 일환으로 선형 타입과 관련된 데이터 생성자 타입체킹을 대대적으로 개편했습니다. 그 결과 GHC는 더 이상 데이터 생성자의 포화(saturated) 적용을 eta-expansion하지 않게 되었고, 컴파일 시간이 줄었습니다 (!14357, !14764).
Matthew는 링크 노드를 처리할 때 드라이버의 오류 처리를 개선하여 T9930fail 테스트에서 일부 실패를 해결했습니다 (!14964).
Sam은 오버로딩된 코드가 함수 화살표 (->)로 인스턴스화되는 Arrow/Category 코드 작성 시 발생할 수 있는 GHC 패닉을 수정했습니다 (#26277, !14760).
Sam은 GHC가 Agda를 컴파일하지 못하는 문제를 해결하기 위해 !14402를 되돌렸습니다 (#26154, !14763).
Sam은 레코드 생성자가 스코프 밖에 있는 상황에서 잘못된 레코드 업데이트를 보고할 때 발생할 수 있는 GHC 패닉을 수정했습니다 (#26391, !14804).
Sam은 뷰 패턴을 사용하는 패턴 동의어(pattern synonym)를 타입체크할 때 발생할 수 있는 GHC 패닉을 수정했습니다 (#26465, !14936).
Matthew는 getModificationTimeIfExists 함수에서 OsPath를 사용하도록 하여 재컴파일 검사(recompilation checking)의 메모리 사용량을 개선했습니다 (!14917).
Andreas의 도움으로 Sam은 Cmm Sink 최적화 패스(변수 선언을 Cmm 레벨에서 인라이닝하는 역할)에 오랫동안 존재했던 심각한 버그를 찾아 수정했습니다 (#26550, !15041).
Sam은 레지스터 할당과 관련된 여러 수정을 구현했습니다. 특히 스택으로 스필링(spilling)하기 위해 레지스터의 포맷을 추적하는 부분과 관련되어 있습니다 (#26542, !15041, #26411, !15121).
Sam은 Cmm 생존성(liveness) 분석 패스에서 서로 다른 포맷에서의 레지스터 할당을 제대로 결합하지 못하던 누락을 수정했습니다 (#26595, #26611, !15121).
Zubin은 GHC 내부 Unique에 사용되는 태그를 재설계하여, 임시 문자 기반 네임스페이스 대신 적절한 ADT를 사용하도록 했습니다 (#26246, !14639). 이는 플러그인 작성자에게도 Unique 생성 시 어떤 태그를 써야 하는지 더 명확하게 해 줍니다.
Andreas는 occurrence analysis의 성능을 조사하며 #26425에서 새 성능 테스트를 추가했습니다 (!14927). 이후 약간 더 엄격(strict)하게 만들어 공간 누수(space leak)를 피하는 등 여러 개선을 했습니다 (!14928).
Andreas는 sizeExpr 계산에서 tick을 처리하도록 추가했습니다 (!14883).
Andreas는 #26056에 대한 회귀 테스트를 추가했습니다 (!14719). 이 이슈는 이전에 tick과 unsafeCoerce# 상호작용을 다룬 그의 작업(!13413)으로 수정된 바 있습니다.
Matthew는 바이트코드 static pointer 엔트리 로딩을 더 지연(lazy)되도록 만들었습니다 (!14900).
Matthew는 바이트코드 라이브러리 지원을 추가하여, 표준 라이브러리(예: base)의 바이트코드를 배포할 수 있게 했습니다. 이를 통해 GHCi 디버거가 이러한 라이브러리 내부로 step-in 할 수 있습니다 (!15062).
Matthew는 GHC가 바이트코드 오브젝트 파일(.gbc)을 생성하도록 지원을 추가했습니다. 이를 통해 컴파일된 바이트코드를 캐시할 수 있어 인터프리터 로드 시간이 개선됩니다 (!14717).
Matthew는 바이트코드 로딩 코드의 리팩터링을 통해 중복이 많은 두 코드 경로를 통합했습니다 (#26459, !14901).
Alex는 바이트코드 링커가 지연성(laziness)에 의존하는 문제와 관련된 이슈를 다뤘습니다 (#25636, !15092).
Rodrigo는 특정 쓸모없는 명령열을 제거(pruning)함으로써 바이트코드 인터프리터의 성능을 개선했습니다 (!14576).
Rodrigo는 #26325를 수정하기 위해 브레이크포인트 인덱스를 Word16에서 Word32로 변경했습니다 (!14691).
Matthew는 GHC 코드베이스 내부에서 “interpreter backend”를 “bytecode backend”로 이름을 바꿨습니다. 이는 코드가 결국 어떻게 실행되는지보다 백엔드가 무엇을 산출하는지를 더 잘 나타냅니다 (!14915).
Alex는 “Trees that Grow”(TTG) 논문에서 소개된 비전을 완전히 실현하기 위해, GHC가 사용하는 구문 트리를 GHC로부터 완전히 독립시키는 작업을 하고 있습니다. 이는 GHC를 더 모듈화하고, 다른 해스켈 도구들이 ghc 패키지 전체에 의존하지 않고도 GHC의 구문 트리를 재사용하기 쉽게 만들려는 목적입니다.
Alex는 Language.Haskell.Syntax.Type가 GHC.Utils.Panic에 의존하지 않도록 분리했습니다 (#26626, !15134). 또한 Language.Haskell 네임스페이스의 다른 모듈들을 GHC 내부 모듈로부터 분리하기 위한 예비 작업을 시작했습니다.
Andreas의 도움으로 Zubin은 Windows에서 DLL 이름 문자열이 사용 중인데도 해제되어 발생하던 세그폴트를 찾아 수정했습니다 (#26613, !15100).
Ben은 MacOS 26에서 -undefined dynamic_lookup가 깨지는 문제를 해결하기 위해, 내장 RTS 클로저의 동적 초기화를 추가했습니다 (#26166, !14902).
Rodrigo는 위의 MacOS 26 관련 깨짐 문제를 해결하는 노력의 일환으로, 특정 심볼들을 ghc-internal에서 rts 패키지로 옮겼습니다 (!14956).
Ben은 메모리가 낮을 때 RTS가 주소 공간 예약(address space reservations)을 다루는 방식을 개선하여 잠재적 루프를 피했습니다 (#26151, !14466).
Matthew는 RTS가 종료(shutdown) 중 이벤트로그를 기록하려 할 때 발생할 수 있는 데드락을 수정했습니다 (#26573, !15068).
Ben은 원자 연산(atomic operations)을 사용하여 non-moving GC에서 발생할 수 있던 런타임 루프를 수정했습니다 (#26053, !14519).
Rodrigo는 Windows DLL과 관련된 RTS의 오래된 로직 일부를 제거했습니다 (!14873).
Hannes는 RTS의 assertion에서 off-by-one 오류를 수정했습니다 (!15019).
Hannes는 IPE 백트레이스를 위한 스택 프레임 주석(annotation) 메커니즘을 기본값으로 활성화했습니다 (#26218, !14721).
Hannes는 스택 디코딩 로직 구현을 ghc-heap에서 ghc-internal로 옮겨, base의 GHC.Stack.CloneStack에서 사용할 수 있도록 했습니다 (!14543).
Matthew는 프로파일드 런타임을 사용할 때 스택 디코딩 로직에 대한 여러 수정을 구현했습니다 (#26507, !14991).
Finley McIlwaine의 이전 작업을 바탕으로, Hannes는 -fno-distinct-constructor-tables 및 -fdistinct-constructor-tables-only 플래그를 도입했습니다. 이는 info-table 프로파일링을 사용할 때 어떤 생성자가 서로 다른 info table을 갖게 할지에 대해 더 세밀한 제어를 제공합니다 (#23703, !14705). -fdistinct-constructor-tables는 일부 프로젝트에서 비정상적으로 큰 바이너리 크기를 유발할 수 있기 때문에 유용합니다.
Ben은 template-haskell 라이브러리의 getQ 문서를 의미론에 더 잘 부합하도록 개선했습니다 (#26484, !14970).
Sam은 “specialise pragma에서의 표현식(expressions in specialise pragmas)” 패치와 관련하여, 기존 Template Haskell 코드가 깨지지 않도록 패턴 동의어를 사용해 Template Haskell 호환성을 개선했습니다 (#26356, !14729).
Andreas는 모듈 의존성 정보를 수집하기 위해 GHC를 호출할 때 Windows에서 긴 경로(long paths)와 관련된 버그를 수정했습니다 (!15060).
Rodrigo는 전역 settings 파일을 제거하고 타깃별 구성(per-target configuration)으로 대체하는 작업에서 추가 진전을 이루었습니다 (#26227, !14554).
Rodrigo는 CFLAGS 같은 플래그가 빌드 단계에만 적용되고 타깃 설정으로 넘어가지 않도록 보장했습니다 (#25637, !14854).
Rodrigo는 Hadrian bindist configure 스크립트에서 오래된 설정 일부를 삭제했습니다 (#26478, !14937).
Ben은 C 컴파일러와 관련된 configure 체크의 불일치를 수정했습니다 (#26394, !14796).
Ben은 Clang이 암묵적 상수 배열(implicit constant arrays)에 대해 경고를 내면서 발생하던 빌드 실패를 수정했습니다 (#26502, !14971).
Ben은 Hadrian으로 빌드할 때 인자 순서에 변화를 주었습니다 (#25281, !14318). 이 작업이 반영되도록 도와준 Cheng Shao에게 감사드립니다.
Andreas는 릴리스 스크립트에 hpc를 추가했습니다 (!15056).
야간 파이프라인의 CI 안정성을 높이기 위한 지속적인 노력의 일환으로, Magnus는 CI의 여러 문제를 해결하여 야간 GHC 빌드를 다시 제공할 수 있도록 했습니다. 여기에는 작은 Python 이슈로 실패하던 Debian 9 CI 잡을 수정한 것도 포함됩니다 (!15127).
Andreas는 jspace 테스트가 덜 흔들리도록(flaky) 개선하여, CI의 AArch64 LLVM 잡에서 반복적으로 발생하던 문제를 수정했습니다 (#25401, !14837).
Zubin은 testsuite way에 따라 달라지는 testsuite 출력 파일을 지원하여, 외부 인터프리터를 사용하던 테스트 실패를 수정했습니다 (#26552, !15078).
Zubin은 불필요한(spurious) 링커 경고가 testsuite 실패로 이어지던 문제를 해결했습니다 (#26349, !14615).
Zubin은 사용자 가이드에서 -fno-xxx 플래그로 가는 링크를 수정했습니다 (#26352, !14794).
Sam은 codes 테스트(오류 코드 테스트 커버리지를 검사)가 Unix와 Windows 파일 경로 차이로 실패하던 문제를 수정했습니다. 이로써 Windows에서 테스트가 더 견고해졌습니다 (#25178, !14778).
Ben은 잡이 릴리스 잡인지 여부를 GitLab “input”으로 만들었고, 이는 메인터이너의 릴리스 관리를 용이하게 합니다 (!14933).
Ben은 FreeBSD에서 CI 실패를 해결하기 위해 FreeBSD에서 split sections를 비활성화했습니다 (#26303, !14782).
Matthew는 일부 테스트가 GHCi에서만 실행되도록 허용하기 위해 testsuite 드라이버에 변경을 가했습니다 (!14914).
Rodrigo는 cabal을 사용해 GHC 컴파일을 테스트하는 test-reinstall 잡을 수정하는 작업에서 진전을 이뤘습니다 (#26202, !14518).
Ben은 ghcup-metadata 잡을 새 OpenCape CI 러너에서 실행되도록 마이그레이션했습니다 (!14814).
Magnus는 새 Windows x86 러너를 설정하고 GHC GitLab 인스턴스의 안정성과 관측 가능성(observability)을 개선했습니다.
Mikolaj는 다가오는 Cabal 릴리스 3.16.1.0 준비에 참여했습니다.
Matthew는 Cabal 이슈 트래커를 도왔고 다른 Cabal 기여자들의 PR을 리뷰했습니다.
Matthew는 바이트코드 라이브러리 파일 및 바이트코드 오브젝트 파일 지원을 추가하기 위한 Cabal 제안서를 작성했습니다.
Matthew는 cabal repl로 대화형 세션을 시작할 때 발생하는 #11107 보고 이슈 중 두 가지를 수정했습니다 (PR #11237).
Zubin은 HLS 2.12.0.0 릴리스를 준비했습니다 (PR #4728).
Hannes는 백그라운드에서 체크되는 파일에 대해 GHC 플러그인이 로드되지 않던 버그를 수정했습니다 (#4631, PR #4749).
Hannes와 Andreas는 반복적으로 발생하던 세그폴트를 진단했으며, 이는 ghc-lib-parser 라이브러리가 RTS에 정의된 공유 CAF를 재사용하는 방식과 관련되어 있었지만, GHC 버전 간 API 변경으로 인해 다른 메모리 레이아웃을 기대하면서 발생한 것으로 밝혀졌습니다 (HLS 이슈 #4674, GHC 티켓 #26033 및 #26553).
Rodrigo는 새 Haskell Debugger 작업을 계속했습니다. 디버거는 우선 다가오는 GHC 9.14 릴리스와 호환될 예정이며, 여러분 모두가 사용해 보길 기대합니다.
Rodrigo는 사용자 지향 튜토리얼 형태로 MuniHac에서 디버거를 발표했습니다. 녹화 영상은 여기에서 볼 수 있습니다.
디버거 개선 사항의 자세한 목록은 변경 로그에서 확인할 수 있습니다. 특히 다음이 포함됩니다:
Matthew와 Rodrigo는 디버거가 사용자 값을 표시하는 방식을 커스터마이즈할 수 있도록 작업했습니다. 자신의 데이터 타입에 대해 DebugView 타입클래스를 인스턴스화하면, 디버거가 값을 확장(expand)하고 표시(display)하는 방식을 제어할 수 있습니다.
Wen은 eventlog-live 개선 작업을 하고 있습니다. 이는 eventlog-socket 라이브러리를 이용해 eventlog의 데이터를 외부 모니터링 프로세스로 스트리밍함으로써, 해스켈 애플리케이션을 라이브 프로파일링하기 위한 라이브러리/도구 모음입니다.
Matthew는 TCP 소켓 생성 지원을 구현하고 eventlog-socket 라이브러리의 테스트 커버리지를 늘렸습니다 (PR #18).
이제 생성된 소켓은 제어 프로토콜(control protocol)을 사용해 양방향으로 사용할 수 있으며, 모니터링되는 프로세스에 추가 힙 프로파일링 정보를 요청하는 명령을 내릴 수 있습니다 (PR #20). 향후 작업에서는 다른 라이브러리들이 명령을 등록할 수 있도록 이 프로토콜을 확장할 예정입니다.