Напомните мне, зачем нужны пустые списки? Почему не сделать так:
data List t = Cons t (Maybe (List t))
Во-первых, тогда не будет контринтуитивных пустых списков разных типов ([] может быть [Int], а может быть и [Foo]).
Во-вторых, если у нас есть список, то мы всегда можем что-нибудь из него достать. Это тупо удобнее, чем матчить и извлечение первого элемента, и получение хвоста списка (и объективно лучше, чем эксепшн "empty list" в рантайме).
Разумеется, списки тут в качестве примера, как самый простой тип данных. Для других коллекций это тоже актуально.
>>1187020 (OP) Пустой список все равно имеет тип, внезапно. Так что [] не может быть [] Int или [] Foo одновременно. А по второму пункту… Определи пожалуйста, как пример, тип функции filter для твоего типа List.
>>1187086 >Так что [] не может быть [] Int или [] Foo одновременно. Строго говоря, истинно пустой список как раз и является [int] и [foo] одновременно, но при первом добавлении элемента тип резолвится и из этой точки конкретный тип уже propagates во все остальные части программы через фантомные типы. А по-настоящему пустой (то есть пустой в каждой точке программы) список как раз имеет полиморфный тип.
>Определи пожалуйста, как пример, тип функции filter Стандартное объявление, только в corner case вместо filter pred [] = [] пишешь filter pred Nothing = Nothing.
>>1187091 Что такое Nothing? Чем оно отличается от []? > data List t = Cons t (Maybe (List t)) Вот у тебя есть такой тип List. Напиши для него сигнатуру типа для функции filter.
В Агде и прочих языках сверхчеловеков из будущего можно указать в типе, что вот этот конкретный список никогда не будет пустым. Такой список на пустоту не надо проверять. Можно вообще все что хочешь указать.
>>1187097 >Что такое Nothing? Чем оно отличается от []? Ясно. Тебе в ньюфаготред.
>Напиши для него сигнатуру типа для функции filter. filter :: List a -> Maybe (List a) же.
>>1187106 Да, но это другое. В агде и ко ты можешь конкретную длину указать, и какой-нибудь concat у тебя будет возвращать список длины n+m, нутыпонел. Я не про это, я про обычные списки в обычных языках без завтипов.
>>1187020 (OP) Возьми и запили себе свой список, в чём проблема? А нам и так збс >data List t = Cons t (Maybe (List t)) Неудобно же >([] может быть [Int], а может быть и [Foo]) НЕ МОЖЕТ! Динамика / нестрогость ненужны
>>1187106 Dependent types в ближайшие пару лет должны быть в хаскеле. Оттуда они в кастрированом виде расползутся по склалам/растаможка/тайпскриптам со временем
>>1187117 Так, нахуй пошел, чепуха, ок? Тот факт, что ты применил Haskell синтаксис совсем не обязывает меня подразумевать что ты там имел ввиду под определенными конструкторами. В твоем ADT определении List нет конструктора Nothing и поэтому ты обосрался с этим > filter pred [] = [] пишешь filter pred Nothing = Nothing
Ну а теперь из своей сигнатуры filter напиши композицию. Для твоего же __List a__ и двух __a -> Bool__ предикатов. Ты не сможешь, клоун
1. Твой список не будет моноидом, со всеми вытекающими. 2. Да с твоим списком даже list comprehension не сделаешь, нахуя он вообще нужен?
>и объективно лучше, чем эксепшн "empty list" в рантайме Maybe действительно решают проблему эксепшнов в рантайме. Только надо делать не "непустой список", а просто объявить head :: [a] -> Maybe a и т.д. Maybe вообще придуман изначально как раз для падучих функций, вот и не надо удалять гланды через жопу.
>>1187410 Ну вот анон выше уже начал перечислять, что не так, например.
>>1187522 > 1. Твой список не будет моноидом, со всеми вытекающими. Давай подробнее, какие конкретно вытекающие.
>list comprehension Considered harmful. Алсо, сделаешь конечно, ты чего.
>а просто объявить head :: [a] -> Maybe a Я в оп-посте уже про это написал, ты чем читаешь? " Во-вторых, если у нас есть список, то мы всегда можем что-нибудь из него достать. Это тупо удобнее, чем матчить и извлечение первого элемента, и получение хвоста списка"
>>1187676 >Давай подробнее, какие конкретно вытекающие Нельзя писать лог в такой список (использовать с Writer)
>Во-вторых, если у нас есть список, то мы всегда можем что-нибудь из него достать. Это тупо удобнее, чем матчить и извлечение первого элемента, и получение хвоста списка" Тебе всё равно придётся матчить получение хвоста списка, потому что его тип Maybe (List t), а не List t. И вдобавок filter, list comprehension тоже будут возвращать Maybe (List t). Сомнительное удовольствие.
>>1187695 >Нельзя писать лог в такой список (использовать с Writer) Бинд райтера использует только mappend, так что писать лог в такой список как раз таки можно (без оборачивания его в мейби).
>Тебе всё равно придётся матчить получение хвоста списка Анон, ну чем ты читаешь? Я же вроде по-русски написал, что с хуевым списком нам придется матчить и head, и tail, а с хорошим списком нам нужно матчить только tail.
>Сомнительное удовольствие. И в чем сомнительность? Давай побольше конкретики и поменьше воды.
>>1187722 >Бинд райтера использует только mappend, так что писать лог в такой список как раз таки можно (без оборачивания его в мейби). Монада состоит не только из бинда. Для return потребуется mappend, которого у тебя не будет. А значит не будет и всей монады. Или ты собрался пользоваться монадой с return = undefined?
>Анон, ну чем ты читаешь? Я же вроде по-русски написал, что с хуевым списком нам придется матчить и head, и tail, а с хорошим списком нам нужно матчить только tail. Не так. С "хуевым списком" придется матчить head и tail, зато filter и list compehension матчить не надо. С твоим списком -- придётся матчить tail, filter и list comprehension. "Если не видно разницы, зачем платить больше?"
Алсо, uncons будет иметь вместо Maybe (a, [a]) уёбский тип (a, Maybe (List a)), который придётся разбирать именно вручную, монадой Maybe тут уже хуй воспользуешься.
>А значит не будет и всей монады. А над Maybe List - будет.
>Или ты собрался пользоваться монадой с return = undefined? Не рассматривал такой вариант, но ход мысли интересный!
>зато filter и list compehension матчить не надо Ну как это не надо? Ты же списки не выкидываешь после компрехеншна - ты с ними работаешь. А значит придется брать вилку и матчить head и tail.
>Алсо, uncons будет иметь вместо Maybe (a, [a]) уёбский тип (a, Maybe (List a)) Ну, тут возможны варианты, кстати. Вполне можно возвращать и первый тип.
>монадой Maybe тут уже хуй воспользуешься. Ой, ну как будто трансформация от Maybe (x, y) до (x, Maybe y) не является тривиальной.
Кстати, я сейчас еще вспомнил, что СПИСКИ НЕ НУЖНЫ же (foldr considered harmful). А православные параллельные деревообразные списки как раз имеют синглтон-список отдельным вариантом.
>>1187813 >Алсо, uncons будет иметь вместо Maybe (a, [a]) уёбский тип (a, Maybe (List a)) Вообще-то (a, [a]) для какого-нибудь List a = Cons a [a]. Да и для ОП-овского, но uncons будет О(n)
>>1187832 >А над Maybe List - будет. Конечно будет, ведь Maybe (List a) эквивалентен обычному списку [a].
Ты по сути предлагаешь считать базовым списком -- непустой, а возможно-пустой список реализовывать как надстройку над ним в виде Maybe (List a).
Почему так не принято делать? Из-за того, что мирок операций, замкнутных относительно List a, оказывается слишком мал, и слишком часто будет нужен Maybe (List a). Решили, что проще сразу "зашить" этот вариант в саму data, и получился [a]. А для кейсов, когда нужны именно непустые -- есть Data.List.NonEmpty.
>>1187891 >слишком мал >слишком часто define "слишком". Ну и вообще сам понимаешь.
>Решили, что проще сразу "зашить" Ну, с null тоже "решили". К тому же дефолтные списки в хаскеле вообще кидают эксепшены в рантайме, так что это хуевый пример. Ну короче так себе аргумент (к тому же ты не спж, так что не знаешь, что именно они там "решали" в дремучих 90-ых).
>А для кейсов, когда нужны именно непустые -- есть Data.List.NonEmpty. Это все понятно - я же говорю о том, есть ли вообще причины содержать по дефолту такую штуку, как пустые датаструктуры. Пока я не услышал ничего, что бы мне самому в голову не пришло (и все это сводится в основном к "ну бля, ну вроде как-то неправильно получается, алгебраисты не оценят").
И опять же, если говорить, например, о православных древовидных списках, это позволит избежать трех вариантов (пара, синглтон, пустой) и оставить два. Хорошо же. И не нужны фантомные типы или полиморфные значения - а это уже серьезный объективный аргумент, система получается гораздо проще, - в отличие от "ну некоторые функции чет не очень удобно писать".
>>1187982 > К тому же дефолтные списки в хаскеле вообще кидают эксепшены в рантайме, так что это хуевый пример.
У них были на то свои причины. Без totality checke всё равно похер, чё там возвращает head.
>Это все понятно - я же говорю о том, есть ли вообще причины содержать по дефолту такую штуку, как пустые датаструктуры
Ну я же вроде сказал, что причины есть. Потому что много где иначе будет нужен Maybe (List a), который и есть суть пустая датаструктура. Это дизайн-решение. Не согласен -- пиши proposal, со всеми pros and cons. Можешь только pros. Пока я увидел только "более лучший head", как-то это маловато для изменения базовой control structure.
>>1187992 >Пока я увидел только "более лучший head" >И не нужны фантомные типы или полиморфные значения - а это уже серьезный объективный аргумент
>Потому что много где иначе будет нужен Maybe (List a) Следуя такому ходу мыслей, получается, что нужно отказаться от мэйби и использовать null, как все нормальные пацаны.
>со всеми pros and cons. Можешь только pros. Ну так о том и тред. А cons жду от анончиков. Пока вроде особо серьезных cons не видно, но может еще какие наглядные контрпримеры кому-нибудь в голову придут.
>>1189305 Обязательно. Не устану лишний раз напоминать, что твоя натуральная трансформация обычного списка в композицию списка и Maybe не привнесла ничего нового, по дороге сломав композицию и моноидальность.
>>1187020 (OP) >Почему не сделать так... Потому что, по определению list - это:
data {a} (A : Set a) : Set a where nil : A cons : A → A → A
И больше ничего. Лишь инициальный рекурсивный тип, параметризованный типом A, со своими алгебраическими свойствами. Он и не должен быть 'интуитивным'. Он должен быть таким, какой он есть. Если тебе нужен другой тип, похожий на list, определяй его как хочешь, но он не будет типом list. Сдаётся мне, что ты - тот же буйный, который требовал отказаться от 'функций с более чем двумя параметрами'.
>>1187106 > Такой список на пустоту не надо проверять В определении не избежать клоза с absurd pattern.
>>1187091 >Строго говоря, истинно пустой список как раз и является [int] и [foo] Внезапно, истинный Nothing может быть и Nothing :: Foo, и Nothing :: Int
>>1187020 (OP) Кул идейка, почему бы тогда не предложить мотематикам заменить все пустые матрструктуры их отсутствием, такая-то оптимизация.
Даже в рамках программирования, наверное прикольно к file does not exist добавить другой файл и получить список с одним файлом, и вообще не иметь отличия между пустой директории и её отсутствием.
>>1202159 Ты не осознаешь разницы между строчкой let foo = Nothing и, гхм, отсутствием этой строчки. Рекомендую для начала почитать, например, вот этот сайт: http://kidsjs.blogspot.com/
>>1202191 Maybe как раз отвечает за возможно отсутвующиее что либо, если чо. Например, юзера из базы пытаешься получить по id - результат Maybe User. А вот если читаешь список его постов - это в любом случае список, но никак не Maybe
>>1187020 (OP) Списки являются типом для вычислений, в результате которых могут получиться 0, 1, или множество значений. Как твой тип справится с 0? Ввести синоним: type Nlist t = Maybe (List t) ?
>>1203052 Если чейним манатками, то матчить не надо. При обычном списке и head, и tail возвращают maybe, а здесь они возвращают сразу t и [t]. Ситуация отсутствия элементов обрабатывается более юниформно.
>>1203380 Ну запили свой maybeHead с maybeTail, зойчем ломать хороший моноид ради двух специфичных функций, проникших в прелюдию? А как ты решишь аналогичную проблему с unJust?
>>1203565 >Лолшто? Твоя аргументация про head и tail. Чем они настолько лучше паттерн матчинга, что ради них стоит ломать моноид? И что там с аналогом head для Maybe - fromJust :: Maybe a - > a ? Ради этой функции теперь и Maybe поломать?
>>1203723 >Чем они настолько лучше паттерн матчинга Список - это data List t = Cons t (List t) | Nil. Первый элемент cons'а называется head, второй - tail. Я не понимаю вопроса.
>Ради этой функции теперь и Maybe поломать? Я не понимаю этого вопроса тоже.
>>1203730 Я тебе делаю встречное предложение же: Отказаться не от пустого списка, а от этих кастрированных функций в пользу безопасного паттерн матчинга и кучи обобщенных интерфейсов - моноид там, всякие вкусные функторы.
>Я не понимаю этого вопроса тоже. fromJust Nothing выбросит исключение так же, как и head []. Стоит ли делать fromJust безопасным аналогичным ОП-посту способом, изменив тип Maybe?
>>1202191 >Ты не осознаешь разницы между строчкой let foo = Nothing и, гхм, отсутствием этой строчки. >Ты не осознаешь разницы между строчкой let foo = Nothing и, гхм, отсутствием этой строчки. Причём тут это? Пустая строка != отсутствие строки, вот и всё.
>>1187020 (OP) картинка говно, там не список, а явная операция сложения, следовательно посону нужно сделать eval и выдать пять. Но автор выебывается, блять, не смотря на то, что обосрался как даун.
>>1203565 > [a] -> [ b ] сделать [a] -> Maybe [ b ], или что? Или что. Я не понимаю о каких монадах ты говоришь и как ты будешь чейнить читаю компоузить функции, когда у тебя Maybe m t там, где ожидается m t. Или ты предлагаешь мне еще и fmap навернуть для такого? Такая то охуенная композиция у тебя получилась, ага.
>>1203735 >в пользу безопасного паттерн матчинга Так когда ты матчишь, например, голову списка, это же просто сахар для проверки на пустоту + head. Речь же не о форме записи идет. Ну и идея оп-поста как раз в том, чтобы избавить от проверок на пустоту каждого списка. Так что я не вижу, в чем тут предложение.
>Стоит ли делать fromJust безопасным аналогичным ОП-посту способом, изменив тип Maybe? Эм, нет, его просто не следует использовать в общем случае, мимокапитан. Алсо, как ты предлагаешь аналогичным ОП-посту способом изменить мейби? Не, это наркомания какая-то, анон.
>>1203968 Ну для непустого списка ты пишешь map succ, а для мейби списка ты напишешь (f map) succ, где f :: ([a] -> [ b ]) -> ([a] -> Maybe [ b ]). Чего ты детский сад какой-то разводишь.
>>1204777 >Так что я не вижу, в чем тут предложение. Вот в этом: head и tail >просто не следует использовать в общем случае Точно так же, как и fromJust
>Алсо, как ты предлагаешь аналогичным ОП-посту способом изменить мейби? data Maybe a = Just [a]
>>1205095 >head и tail >>просто не следует использовать в общем случае То есть ты предлагаешь отказаться от списков вообще, ну заебись. Перечитай еще раз предыдущий пост.
>data Maybe a = Just [a] Хотя не перечитывай, ты просто хуйню несешь. Забей.
>>1204777 > Ну для непустого списка ты пишешь map succ, а для мейби списка ты напишешь (f map) succ, где f :: ([a] -> [ b ]) -> ([a] -> Maybe [ b ]). Йобаный стыд! Давай по порядку. Твои сигнатуры просто не тайпчекаются. Причем тут map вообще? И, внезапно, сейчас map пишется как для непустого, так и пустого списков. Или ты под композицией имеешь ввиду функцию высшего порядка map? Интересно! Вот это композиция: (.) :: (b -> c) -> (a -> b) -> a -> c Ну или это (<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c Для Maybe [t] я напишу fmap (map succ) и не стану придумывать f.
А теперь еще раз вопрос – если filter :: List t -> Maybe (List t), map :: (a -> b) -> List a -> List b, то что нужно написать для вычисления эквивалентного этому map (const "foo") . filter (const True) . map (const "bar")?
Ты конечно можешь пойти выдумать новый комбинатор для типа t -> Maybe (List t), или пижже два комбинатора, чтобы потом опять к (.) можно было вернуться, лол. Но можно и одним, привычно тыкая Just везде для заворачивания в необходимый тип, т.к. инварианта Nothing в многих функциях просто не будет. Предположим в этом мире уже нельзя делать пустой список, твой proposal влили делай checkout за щеку. Смотри на свой тип f :: ([a] -> ) -> ([a] -> Maybe ). Я правильно понимаю, что это тождественно (List a -> List b) -> List a -> Maybe (List b)? Если да, то напиши пожалуйста пример функции g :: List a -> List b такую, что был для любого произвольного списка ls :: List _ следующе выражение было бы истинно: f g ls = Nothing. Ты бы мог конечно очевидно нет попробовать написать хотя бы пару функций из Data.List. для проверки своих догадок. Так бы ты увидел, что для сохранения всей той выразительной мощи Haskell, которая имеется сейчас, тебе бы пришлось придумать новый тип вида type List = (Maybe :/: NonEmpty) :: -> * с написанием всех инстансов для него. И уже этот тип использовать терминирующим в реализациях filter / tail / delete / drop и прочее (даже instance Monoid сможешь написать). И уже в такой реализации ты получаешь задуманное – head :: List a -> a. Только List еще unWrap'нуть нужно. Т.е. по сути редизайн всего типа данных, а не этот не выдерживающий никакой критики Cons t (Maybe [t]). Все, что ты тут навыдумывал выглядит вот так: [] + [t] ~> Nothing :: Maybe + (Cons t (Maybe (List t))) :: List. Пусть не на уровне самого типа, но типов функций для работы с ним. По сути это не список без пустых значений, а просто пустой список эмулируется через Maybe жопу. Зачем? Не матчить head? Хз зачем это вообще, когда есть uncons.
>>1205135 >То есть ты предлагаешь отказаться от списков вообще Это ты сам додумал? Я предлагаю ограничить употребление head/tail в пользу манаток и других обобщенных интерфейсов, где проверка на пустоту уже реализована под капотом, как и проверка на Nothing у Maybe.
>Хотя не перечитывай, ты просто хуйню несешь. Забей. Ты мне лучше скажи чем fromJust хуже пары head / tail, что ты готов его выкинуть, а вторые холишь и лелеешь? Это ведь по сути одно и то же, просто для разных контейнеров. Как-то не последовательно с твоей стороны.
>>1204777 Ты даун, просто признай, что обосрался, + это операция сложения практически во всех языках. Какого хуя ты вообще про патмат рассуждаешь, если даже с оператором справится не можешь.
>>1205207 >Твои сигнатуры просто не тайпчекаются. Ой, блядь, ну ты же понял, что я имел в виду f (map succ) с той сигнатурой, которую написал.
>Или ты под композицией имеешь ввиду функцию высшего порядка map? Интересно! Чего блядь?
>Для Maybe [t] я напишу fmap (map succ) и не стану придумывать f. А нахуя ее придумывать-то?
>что нужно написать для вычисления эквивалентного этому Блядь, у тебя filter (const True) берет х и возвращает Maybe x; map (const "bar") берет x и возвращает x. Тебе нужно получить композицию этих двух функций, которая берет х и возвращает Maybe x. Ты реально не можешь сам додуматься, как это сделать? Ты же абзацем выше блядь все написал, просто пиздец какой-то.
>выдумать новый комбинатор для типа t -> Maybe (List t) Вообще пиздец какой-то.
>f g ls = Nothing Ты, блядь, реально упоротый. У тебя g возвращает список, который по определению непустой. Дальше сам додумаешься?
>И уже этот тип использовать терминирующим в реализациях filter / tail / delete / drop Ну молодец, спустя неделю до тебя дошло, что написано в оп-посте.
>Т.е. по сути редизайн всего типа данных, а не этот не выдерживающий никакой критики Cons t (Maybe [t]). Ты, блядь, реально упоротый и несешь ебаную хуйню. Cons t (Maybe [t]) - это и есть "редизайн всего типа данных", поскольку это другое, блядь, определение этого типа данных.
>По сути это не список без пустых значений, а просто пустой список эмулируется Лол. Я не знаю, что там у тебя "по сути" в твоей гуманитарной головушке, но по определению дататипа он пустым быть не может. С тем же успехом можно сказать, что "по сути nil в х-ле есть)) просто он эмулируется через Maybe)))0)". Пиздец просто.
>Зачем? Может ты таки прочитаешь тред, прежде чем в него писать?
>когда есть uncons Ну так uncons возвращает maybe, в котором хвост может быть пустым.
>>1187020 (OP) ОПушка, голубчик, а сделай-ка свой список представителем класса Monad, но только чтобы все по понятиям, с доказательствами корректности. Тогда и поговорим.
>>1205588 > я имел в виду f (map succ) Не ебу, что ты там имел ввиду. И какого хуя я вообще должен что-то там додумывать? Я уже пробовал, но твоя шизофреничная манера менять сигнатуры от поста к посту меня напрягает. То ты используешь [t] там, где тебе удобно, то у тебя [t] и Nothing одного типа. И ты попросту не привел ни одного примера со своим чудесным List t. Ровно как и пример хоть какой композиции. То, что ты называешь пиздец какой-то. > нужно получить композицию этих двух функций, которая берет х и возвращает Maybe x Хуя ты лавируешь, в очередной раз! Ты зенки то блять разлупи и еще раз перечитай строчку. Там после filter еще раз map происходит. Я могу сделать функцию композиции List x -> List x и List x -> Maybe (List x). Хуле там делать то, вот она (.) ! Я у тебя это и не спрашиваю. Я спрашиваю как ты предлагаешь мне делать композицию произвольного количества любых функций для работы со списками, как это сейчас есть в Haskell через точку. Как мне делать юниформную обработку списков, когда одни функции возврщают List t, а другие Maybe (List t)? В Just заворачивать? А результат filter :: List t -> Maybe (List t) как будет в map :: List t -> List передаваться? Напиши мне f :: (List t -> Maybe (List t) -> (List t -> List t) -> List t. Или тогда определи сигнатуры новых функций для работы с непустыми списками. Нахуй мне твой тип без функций вообще нужен? > дошло, что написано в оп-посте А что у тебя там написано? Ты там сконструировал тип данных? Ты привел пример работающего кода сложнее head / tail, где твоя реализация будет иметь преимущество? Может ты сравнил exhaustive pattern matching для [t] и List t? Нет, нет, нет. Там ты написал, что [] может быть разных типов, епт!
>И какого хуя я вообще должен что-то там додумывать? Ну предполагается, что ты в теме и понимаешь, о чем речь идет.
>меня напрягает Расслабься, анончик, ступни себе помассажируй.
>то у тебя [t] и Nothing одного типа. Чего блядь? Антигаллюциногены внутривенно, срочно!
>Ровно как и пример хоть какой композиции Что тебе непонятно-то, я ж вроде джва раза уже объяснил? Монад тьюториал читни какой-нибудь, или чо?
>Как мне делать юниформную обработку списков, когда одни функции возврщают List t, а другие Maybe (List t)? Я же написал уже, через лифтинг этих функций в монаду.
>А результат filter :: List t -> Maybe (List t) как будет в map :: List t -> List передаваться? Ясно, в чем проблема. Прочитай какой-нибудь монад тьюториал, анон.
>Напиши мне f :: (List t -> Maybe (List t) -> (List t -> List t) -> List t. У тебя скобки несбалансированные, парсинг еррор.
>Там ты написал, что [] может быть разных типов, епт! Ну, ты с этим не согласен, или что? Установи себе hugs да проверь сам.
>>1211839 Шизофреник, блять, код покажи! Что ты мне тут эту мантру повторяешь монад тьюториал, лифтинг в монаду? > filter :: List t -> Maybe (List t) … map :: List t -> List Вот эту композицию оформи. Там же 3 строчки, епт! Или обосрамс?
>>1212352 Ну если ты не понимаешь, как работают монады, то что мне тебе еще посоветовать? Я понятия не имею, что ты еще от меня хочешь. Алсо, код этот я тебе выше уже писал, перечитай тред.
>>1212604 Конечно ты не понимаешь. Ты ведь просто не ебешь, что такое композиция и в чем суть проблемы, что вся обработка твоего непустого списка переехала в монаду Maybe. Не понимаешь, что есть алгебра, что есть семантика. Нахуй оно тебе, правда? Можно свести список к получению головы, больше ведь операций нет. Шо блять за моноид? Ой не, нахуй не нужно! Во бля, паттерн матчинг головы! Look mum! Non-empty list, just look… Не привел ни одного примера, который тайпчекается, а на все вопросы показать как будет реализована конкретная сигнатура ты закрываешь глаза, упорно повторяя манатки, монад тьюториал и прочую истерию, наивно полагая, что только ты тут один знаешь Haskell. Удобно, хуле.
>>1211969 >оп-пост предлагает убрать именно нуль. Оп предлагает убрать нейтральный элемент. У чисел, в зависимости от ассоциативной операции, разные нейтральные элементы.
>>1187020 (OP) >Во-вторых, если у нас есть список, то мы всегда можем что-нибудь из него достать. Это тупо удобнее, чем матчить и извлечение первого элемента, и получение хвоста списка (и объективно лучше, чем эксепшн "empty list" в рантайме). Перенос матчинга на шаг позже вовсе не означает "решение проблемы".
Монад туториал не читал, для твоего случая это и не требуется.
data List t = Cons t (Maybe (List t))
Во-первых, тогда не будет контринтуитивных пустых списков разных типов ([] может быть [Int], а может быть и [Foo]).
Во-вторых, если у нас есть список, то мы всегда можем что-нибудь из него достать. Это тупо удобнее, чем матчить и извлечение первого элемента, и получение хвоста списка (и объективно лучше, чем эксепшн "empty list" в рантайме).
Разумеется, списки тут в качестве примера, как самый простой тип данных. Для других коллекций это тоже актуально.