← На главную

Автор реализует row polymorphism из PureScript в type checker Nix

23.06.2026 13:04 · hackernews

Автор считает, что одна из главных проблем статически типизированных языков — отсутствие нормального вывода типов для анонимных записей. Анонимные записи — это объекты без заранее объявленного типа, как в JavaScript, Python, Nix или JSON. В статически типизированных языках их поддерживают TypeScript, C# и PureScript, а вот в Haskell нет.

Вывести тип для простого литерала вроде { name: "Alice", age: 25 } легко: каждый литерал получает свой тип, и на выходе получаем { name: String, age: Number }. Но проблема возникает с функциями. Если написать person => person.name, то типом person должен быть { name: String | ... } — запись, у которой есть поле name, и ещё может быть что угодно.

Тут есть два подхода. Первый — subtyping (как в TypeScript): запись { name: String } считается подтипом любой большей записи. Второй — row polymorphism (как в PureScript): вместо многоточия используется именованная «строка» — row variable, например { name: String | r }. Это позволяет абстрагироваться от остальных полей.

Row polymorphism особенно важен для операций вроде record extension — добавления или замены поля. Например, функция, которая добавляет полю queen значение true. Её тип будет { queen: Maybe Boolean | r } -> { queen: Boolean | r }, где r — те же поля, что и на входе. В TypeScript такое пришлось бы писать через Omit<T, 'queen'> & { queen: boolean }, что гораздо громоздче.

Автор работает над type checker для Nix, где есть оператор // (конкатенация записей). Row polymorphism — единственный способ нормально вывести тип для него, и следующая статья будет как раз о том, как это реализовать.

Читать оригинал →