PunchAPC rally disruption: SDP rejects Nasarawa claims against Al-Makura, AdamuCNN Türkİzmir'de uyuşturucu operasyonu: 7 gözaltıThe Jerusalem PostDemocracy was top Jewish voter concern in midterms, not Israel or antisemitism - poll한겨레‘AI 공포’에 안전자산으로 몰렸다…금값, 일주일 전보다 5% 넘게 올라ZDF heuteAktuelle Pressemitteilungen des ZDFSouth China Morning PostHow Japan’s 660 most wanted stay hidden: slums, day labour and forged IDsRolling StoneNile Rodgers Defends AI Use in Music Video: ‘We Created Everything … The AI Did What We Told It to Do’매일경제피노, 1830억 원 규모 유증 단행…이차전지 소재 사업 체질 개선Malay MailThe iPhone Duo is my new favourite iPhone but is it for you?The Sydney Morning HeraldBeau Lamarre-Condon trial live updates: Alleged double murderer, former NSW Police officer returns to witness box, asked about relationship with Jesse BairdBillboardAmy Winehouse’s ‘Back to Black’ Reissue Sparks Top 10 Chart ReturnCBS NewsMississippi Senate race is toss-up, with razor-thin margin
The Daily Newsstand · Free, Always
Friday, November 6, 2026

Полярные типы данных в Edva

Translate

Полярные типы данных (Ramifications) в языке Эдва (Edva): единая замена для bool, Option и Result

В большинстве языков программирования понятия «истина/ложь», «значение есть/значения нет» и «успех/ошибка» живут в разных мирах. Для первого существует примитив bool и конструкции if/else, для второго — Option<T> (Maybe a), для третьего — Result<T, E> (Either a b). У каждого из них свои конструкторы (true/false, Some/None, Ok/Err) и свой набор комбинаторов.

Системный язык программирования Edva, спроектированный без единого ключевого слова, сводит все бинарные исходы к единому примитиву на уровне системы типов — алгебраическим разветвлениям (Algebraic Ramifications, или коротко — Rams).

Четыре формы полярного типа и представление в памяти

В Эдве любой бинарный исход описывается типом с двумя полюсами: положительным (левым) и отрицательным (правым). В зависимсти от того, несут ли полюса полезную нагрузку, существует ровно четыре формы:

Форма типа

Положительный полюс

Отрицательный полюс

Что заменяет в классических языках

<>

<+>
пусто

<->
пусто

bool (true / false)

< T | >

<+ value +>
значение типа T

<-->
пусто

Option<T> (Some(T) / None)

< | E >

<++>
пусто

<- error ->
ошибка типа E

Статус выполнения (Ok(()) / Err(E))

< T | E >

<+ value ->
значение типа T

<- error +>
ошибка типа E

Result<T, E> (Ok(T) / Err(E))

На уровне LLVM IR значения полярных типов не требуют аллокаций в куче или сложных вложенных тегов — они укладываются в компактное необёрнутое (unboxed) представление { i1, i64 } (бит полярности плюс полезная нагрузка), а в случаях, когда тип уже представляет собой указатель, не нужен даже бит полярности, поскольку второй полюс можно выразить нулевым адресом, и представление сокращается до { i64 }.

Конструкторы полюсов

Для явного создания значений полярного типа используются симметричные символьные конструкторы:

  • Положительный полюс: <+>, <+ val +>, <++>, <+ val -> (пустой успех или успех со значением val).

  • Отрицательный полюс: <->, <-->, <- err ->, <- err +> (пустая неудача или неудача со значением err).

Взаимодействие с оператором выбора и стражами | и [...]

Поскольку в Edva нет ключевых слов if, else, match или switch, управление потоком строится на операторе выбора, который выглядит так:

значение [страж ветвь]+

Для обычных значений стражи в квадратных скобках проверяют равенство или предикат, а | выступает веткой по умолчанию:

  classify = score =>
   score [100]    "perfect"
         [99, 98] "almost perfect"
         [> 90]   "distinction"
         [> 50]   "pass"
         |        "fail"

Когда же слева от оператора выбора | оказывается полярный тип (ramification), срабатывает позиционное сопоставление:

  • первая ветка после | обрабатывает положительный полюс (+),

  • вторая ветка после | обрабатывает отрицательный полюс (-).

Если полюс несет значение, внутри ветки к нему можно обратиться через позиционный плейсхолдер _ (или секцию оператора):

// Функция возвращает < Int | > (аналог Option<Int>)
res = find_target(10, 7)

// Первая ветка берет значение из <+ val +>, вторая срабатывает на <-->
res | print_int(_) | print $ "Not found"

Никаких if let Some(x) = res или match res { Some(x) => ..., None => ... }: полярность значения напрямую выбирает нужную ветвь выражения.

Циклы как генераторы полярных типов (>--)

В императивных языках поиск элемента в цикле обычно требует мутабельного флага found = false или досрочного return из функции. В Edva циклы (@) являются выражениями, которые с помощью оператора выхода >-- естественным образом возвращают < T | >:

// Цикл ищет цель в диапазоне 0..count и возвращает < Int | >

find_target: Int, Int => < Int | >
find_target = count, target =>
   count @ i =>
      i [target] -->         // если i == target, прерываем цикл (break)
   >--
      target                 // значение при срабатывании -->

Механика работы >--:

  1. Если внутри цикла сработал оператор прерывания -->, блок после >-- вычисляет результирующее значение и автоматически упаковывает его в положительный полюс <+ target +>.

  2. Если цикл прошел до конца без прерываний, выражение целиком возвращает отрицательный полюс <-->.

Полученный результат тут же готов к передаче в оператор выбора | или дальше по конвейеру.

Композиция и обработка ошибок: $>> и --!

Когда функции возвращают < T | E > или < T | >, Edva предлагает два способа композиции без ручного разбора веток: конвейерное монадическое связывание и постфиксное пробрасывание.

1. Монадический bind ($>>)

Оператор $>> пропускает положительный полюс через цепочку функций, а при возникновении отрицательного полюса (<- err -> или <-->) коротко замыкает вычисление и пробрасывает его на выход:

find_user: String => < User | Error >
find_user = id =>
   query_db(id) $>> validate $>> (<+ _ +>)

// выражение с подчёркиванием в скобках это лямбда, эквиалентно x => <+ x +>

Если query_db или validate вернут отрицательный полюс с ошибкой, вся цепочка немедленно завершится с этим же отрицательным полюсом типа Error: <- error ->.

2. Постфиксная распаковка и ранний возврат (--!)

Для последовательного кода, где нужно распаковать несколько полярных значений подряд, используется постфиксный оператор --!:

load_config: String => < Config | Error >
load_config = path =>
   raw = io::read_file(path)--!
   cfg = json::parse(raw)--!
   <+ cfg +>

Если io::read_file(path) возвращает <+ content +>, оператор --! извлекает content и связывает его с raw. Если же вернулся <- err ->, выполнение load_config прерывается (по аналогии с тем, как --> прерывает цикл), возвращая ошибку вызывающей стороне.

Итог: единая алгебра вместо зоопарка типов

За счет объединения булевой логики, опциональных типов и результатов с ошибками в четыре формы < ... | ... >, Edva избавляется от дублирования концепций:

  • Вместо отдельных bool, Option и Result — единый параметризуемый тип { i1, i64 }.

  • Вместо if/else, match, .unwrap_or() и if let — единый оператор выбора | с позиционными ветками.

  • Вместо ручных флагов выхода из циклов — оператор >--, связывающий управление циклом напрямую с системой типов.

Ссылки

View the original on Хабр →

KioskNews shows a cleaned-up reading view extracted from the publisher’s page — the original always lives on their site, not ours.