Типобезопасные матрицы — извечная тема. О нужности их спорят, а для реализации списков с длинной на уровне типов пишут целые языки. Мне показалось странным, что на Haskell до сих пор нет ни одного варианта, который удовлетворял бы вменяемым критериям удобства и безопасности. Есть какие-то причины отсутствия готовых библиотек или они просто не_нужны? Давайте разбираться. Верный способ понять, почему чего-то (что непременно должно быть!) нет — это попробовать сделать это самому. Попробуем.. Первым же делом вспоминается (по крайней мере мне) статья о type level haskell, где, с помошью DataKinds, GADTs, KindSignatures (краткое пояснение того, где и зачем они используются — ниже) вводятся индуктивные натуральные числа, а за ними и векторы, параметризованные длиной: KindSignatures используется для указания того, что n может быть не любым типом с kind'ом * (как например параметр а в этом же примере), а значением типа Nat, поднятым на уровень типов. Возможность этого обеспечивается расширением DataKinds. GADTs же нужны для того, чтобы конструктор мог влиять на тип значения. В нашем случае конструктор Nil построит именно Vector длины Zero, а конструктор :| присоединит к вектору во втором аргументе элемент типа a и увеличит размер на единицу. Для более подробного и правильного описания можете прочитать статью, на которую я сослался выше или Haskell Wiki. Что же. Кажется, это то, что нам нужно. Осталось только ввести матрицу: И это даже будет работать: Проблемы этого подхода уже сейчас лезут изо всех щелей, но жить с ними можно, продолжим.  Пока с матрицами ничего нельзя сделать, они бесполезны, поэтому, давайте, для начала, попробуем умножить матрицу на число: Посмотрим, что получилось: С тем же успехом мы можем описать и сложение матриц: Однако проблемы овертайпинга вылезут довольно быстро: когда вы захотите, например, научиться перемножать матрицы или хотя бы транспонировать. Давайте попробуем, взяв за основу реализацию транпонирования обычных списков из стандартной библиотеки: Выглядит прилично, но GHC считает иначе (и совершенно справедливо). Что это значит? Компилятор сообщает, что из посылки m есть Zero не следует n есть Zero.
Для того, чтобы избавиться от этой проблемы, мы бы могли вернуть нe Nil, а вектор Nil'ов длины n. То есть спустить тип n на уровень значений, чего мы сделать не можем, ведь n сотрётся и в рантайме существовать не будет. Что ж, предыдущая попытка развалилась, как только нам понадобилось что-то большее, чем размеры на типах. В Haskell нет зависимых типов, поэтому предыдущий подход не годится от слова совсем. Внутрянку реализуем по-старинке через список списков. Но интерфейс. Можно ли его сделать безопасным и удобным?  Вообще в Haskell существует как минимум два решения: linear и laop, и у каждого из них есть проблемы: Давайте попробуем совместить типобезопасность linear и гибкость laop. Но как? Можно было бы воспользоваться вектором из предыдущей попытки, но он имеет одну проблему, о которой до этого деликатно умалчивалось: конструирование матрицы через векторы чрезмерно вербозно, а сообщения об ошибках обещают быть нечитаемой последовательностью из кучи Succ и Zero: Поэтому для указания длины и ширины мы воспользуемся натуральными числами, поддерживаемыми компилятором GHC, а векторы попробуем заменить на что-то принципиально другое. Но что? TemplateHaskell (TH) — расширение языка, открывающее возможности мета-программирования, а значит, для расширения языка. Весь описанный далее код будет исполняться во время компиляции. За основу матричного синтаксиса был взят вариант matlab:  Давайте формализуем синтаксис: Где  И напишем парсер (конечно же, на комбинаторах!). Полную реализацию которого можно найти здесь: Тут Exp — кусок AST языка Haskell, поэтому вывод типов получится поручить компилятору, а самим просто провалидировать распарсенный список и вписать его размерности в тип матрицы (В сущности нам осталось лишь построить наше AST на основе готовых выражений). Далее введём матрицу c небезопасным конструктором, который будет скрыт от пользователей, и функцию, которая построит нам AST с готовой матрицей Осталось всего ничего: построить из готового кода QuasiQuoter и можно пользоваться! Давайте попробуем: TH дал прекрасные возможности для расширения синтаксиса и возможностей языка, поэтому на одних матрицах я не остановился и написал ещё один занимательный макроc для декларативного построения матриц операторов. Пример работы представлен ниже, а ознакомиться со всеми результатами работы вы можете по ссылкам на репозиторий и страницу на hackage Рабочие типобезопасные матрицы на Haskell не то, что бы тривиальная задача. Получились ли мои матрицы типобезопасными? Скорее нет. Они имеют типобезопасный и гибкий интерфейс, но реализация функционала отдана на откуп разработчику (то есть мне), корректность которого компилятор гарантировать не может.  Хорошо это или плохо, но в зоопарке матриц на хаскеле прибавление. А вы решайте: нужны или нинужны. Дублирую ссылки на репозиторий и hackage Замечания, предложения, а также пуллреквесты, приветствуются. Пишу на Haskell