Release manager of Haskell Platform пишет, что уходит, т.к. не осилил морально переход на FTP в 7.10 (это когда вместо and :: [Bool] -> Bool теперь and :: Foldable t => t Bool -> Bool и с остальными прилюдными ф-ями аналогичная метаморфоза).
Обобщили, типа. Раньше самые популярные комбинаторы (map/fold/all/any и т.д. и т.п.), работали со списками, а аналогичные операции для других контейнеров надо было вызывать с именем модуля или еще как следить, чтобы они в пространстве имен не толкались друг с другом. Но поскольку суть у них одна, общую суть вынесли в пару интерфейсов, теперь эти функции применимы к самым разным контейнерам без танцов с импортами. Но типы их стали чуть сложнее для новичков, это многих отталкивает. Впрочем, таких меньшинство, ибо было в свое время голосование, сообщество в целом решило переходить. Переход произошел при смене версий с 7.8 на 7.10, вроде. В свежей Платформе уже эти новые интерфейсы.
Да ну, порой однобуквенные обозначения реально убивают же.
type Optical p q f s t a b = p a (f b) -> q s (f t) type Over p f s t a b = Optical p (->) f s t a b type Optical' p q f s a = Optical p q f s s a a type Optical' p q f s a = Simple (Optical p q f) s a type Optic p f s t a b = p a (f b) -> p s (f t)
Это не тот пример ;-) В случае всяких "and" всё куда проще, впрочем, как и в примере от Valentin Budaev. Тем более, что (Traversable t, Monad m) => это уже вполне так себе документация. Ну не стопицот буковок же там стоит?
> Тем более, что > (Traversable t, Monad m) => > это уже вполне так себе документация.
Вот именно. Без этого куска документации я не могу распарсить (a -> m b) -> t a -> m (t b), а (a -> monad b) -> traversable a -> monad (traversable b) - могу, без проблем.
Более того, штука вся в том, что в случае (a -> m b) -> t a -> m (t b) все равно при чтении это обязательно переводится в (a -> monad b) -> traversable a -> monad (traversable b) в уме, вопрос:
зачем заставлять читателя каждый раз заниматься разбором и запоминанием документации, а потом переводом?
Проблема не в сложности типа, он простой. Проблема в излишней когнитивной нагрузке, которая ложится на читателя, отбитому лень напечатать три лишних буквы, он печатать не будет и оставит читателю догадываться из контекста. Точно также можно не печатать пробелы, ну патаму шта лень, а и без пробелов же текст понятен? Тест не становится сложнее, это по факту тот же текст с тем же смыслом, просто без пробелов. Но его понимание будет требовать _значительно_ больших когнитивных усилий.
Есть и еще один момент: короткосрочная память не в состоянии сколько-нибудь эффективно работать более чем с полдесятком объектов. Следствие: если в строке кода более чем пара подобных обобщенных ф-й, то вы проиграли, задача "мгновенного" парсинга кода лежит за физиологическими пределами человеческого мозга, у вас кешмисс.Надо тратить время на сброк информации в л2 кеш, а потом парсить с обращением к нему - что, конечно, дороже.
> FooBar fooBar = new FooBar - это перебор и копипаста
Никто и не спорит. Но здесь не требуется подстановка, в отличии от примера с типом. А подстановка - очень дорогая для человеческого мозга операция.
Видимо, это уже вопрос вкусом и привычек. То есть, обсуждать бесполезно. Вон как для GHC замечательно поступили — проголосовали!
> зачем заставлять читателя каждый раз заниматься > разбором и запоминанием документации, а потом переводом?
Ну не канает эта аргументация в случае "and" и всякого прилюдного, собственно, о чём и речь в посте. А для более других примеров — очень может быть, что и соглашусь.
> строке кода более чем пара подобных обобщенных ф-й
"Подобных", это значит, что речь таки идёт о теме поста? Ну тогда ерунда это. Я вот оочень быстро привык уголком глаза на такое смотреть. Только чууточку сложнее. чем со списками получается.
Да и часто ли люди смотрят на тип and?? ;-) Только в справочных целях.
Вот что ошибки вывода типов усложняются, это уже более существенно, но об этом речи не идёт.
> Ну не канает эта аргументация в случае "and" и всякого прилюдного, собственно, о чём и речь в посте.
Поясните, почему не канает. Я так понял, подразумевается, что какой-нибудь mapM - это стандартная библиотека, с-но, вам и не надо парсить все эти траверсаблы и вы даже не заметите, а если заметите - то надо бы привыкнуть, ведь это все-таки стандартная библиотека? Но ведь подобный обобщенный стиль стимулирует и вас свои ф-и писать в таком же обобщенном стиле, то есть если ваша ф-я раньше использовала mapM и принимала List, то теперь вы ее напишете принимающей Traversable. Или вы Имели ввиду что-то другое?
> Да и часто ли люди смотрят на тип and?? ;-)
Я согласен, что если бы это ограничивалось каким-то конечным набором библиотечных ф-й, то все в порядке. Но, см. выше - на практике это будет приводить к тому, что вы будете свои ф-и писать в таком же обобщенном стиле, у вас в коде будут Traversable t => ..., кому-то ваш код надо будет читать. То есть речь не о ф-ях прелюдии, речь о ф-ях пользователей.
Подобная подстановка в любом случае требует дополнительных усилий (с этим, думаю, вы спорить не будете). Другое дело, что вы уже можете заучить, что m - это Monad, t - Traversible и т.д., с-но вы при виде (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b) никаким парсингом не занимаетесь, на часть (Traversable t, Monad m) по сути и не смотрите, а сразу же читаете (a -> m b) -> t a -> m (t b) как оно есть. Вопрос задротства, вобщем-то, но я не считаю, что писать код, полагаясь на то, что ваш читатель в подкорке уже заучил, что t = Traversible - хорошая идея. Вообще, здесь в синтаксисе проблема, и она, к сожалению, не решается.
>> Ну не канает эта аргументация в случае "and" >> и всякого прилюдного, собственно, о чём и речь в посте. > Поясните, почему не канает.
Потому, что простые примеры очень, легко охватываются взглядом. И какая-то сложность в них присутствует только для новичков, но не связана с однобуквенными переменными или в виде слов. Может быть, там и попадётся что-то 'сложное', но с ходу, не вспоминается.
> а если заметите - то надо бы привыкнуть, > ведь это все-таки стандартная библиотека?
Нуу, эти рассуждения вообще хоть чего-то стоят только применительно к новичку. Если кто-то хоть поверхностно асилил класс Monad, то уже никаких проблем не будет. Да в общем-то, никаких проблем нет осилить и Traversable. Любой "Gentle Introduction" содержит достаточно сведений, чтоб это было сделать несложно.
> Но ведь подобный обобщенный стиль стимулирует > и вас свои ф-и писать в таком же обобщенном стиле, > то есть если ваша ф-я раньше использовала mapM > и принимала List, то теперь вы ее > напишете принимающей Traversable.
Совсем не обязательно. Моя функция может работать и со списками, например — тип выведется. Но если понадобится что-то более другое, чем список, то можно просто продолжать работать, не исполняя всяких "танцев с import'ами" (что-то импортировать, что-то нет, что-то qualified, ...), о чём упоминал аффтар в http://thedeemon.livejournal.com/104785.html?thread=1783377#t1783377
> Потому, что простые примеры очень, легко охватываются взглядом.
Я говорю не об абсолютных величинах, а об относительных. Две-три секунды на подстановку - это вроде как "легко охватывается взглядом", но для подобного кода - неоправдано много. И примерно в бесконечность раз больше, чем когда подстановки нет.
> Нуу, эти рассуждения вообще хоть чего-то стоят только применительно к новичку. Если кто-то хоть поверхностно асилил класс Monad, то уже никаких проблем не будет.
Да я согласен, что если речь идет исключительно о стандартной библиотеке - то все равно все привыкнут. Это не проблема.
> Совсем не обязательно.
Обязательно, потому что такое комьюнити. Для хаскеливтосв чем обобщеннее - тем лучше. Если хаскелист может написать траверсабл вместо листа - он пишет траверсабл, а о том, что в его ф-ю ничего кроме списка не прилетит и прилететь by design не может - даже не задумывается. Именно об этом человек по ссылке из оп-поста и плачется, а не о том, что у mapM или у другой какой-то библиотечной функции чуть-чуть тип поменялся (на это пофиг всем).
Сейчас все бросятся переписывать типы [a] -> Integer на (Traversable t) => t a -> Integer бодро.
Сжатый синтаксис - это по определению такой, при котором информация не теряется. В рассматриваемых примерах она теряется как раз - исключается дублирование, а это всегда потеря.
Отсутствие потерь будет только при условии наличия соглашения, что t - это всегда traversable, m - monad и т.д.
Но подобное соглашение невыполнимо в хаскеле. Можно было бы добавить возможность определять соответствующие сокращения, но пока ее нет - будет то, что по ссылке в первом посте. Потому что, возвращаясь к началу - на хаскеле пишут отбитые люди.
Я живу в стране, где именно так и пишут - без пробелов. :) Не сказал бы, что сильно мучаются при чтении. Это я не столько в защиту ваших оппонентов, сколько про слабость примера.
Естественно - ведь это тот же текст :) Очевидно, никто не использовал бы систему письменности, которая вызывает реальные трудности при чтении (в условиях достаточно свободной конкуренции она бы быстро отмерла). Как и однобуквенные невнятные обозначения тоже существенных сложностей не вызывают, вопрос в сравнительном удобстве. Конечно, и без пробелов текст легко парсится, и типы с траверсаблами легко парсятся, но только если писать с пробелами - то текст парсится проще. И типы парсятся проще, если в голове их не надо подставлять. Так что многие языки приобрели пробелы как раз в результате эволюции, которая не является необходимой (и так можно было читать не особо напрягаясь), но является желательной (почему бы не упростить еще, если можно?). А вот примеров обратной трансформации я не припомню.
Так что аналогия как раз весьма точная.
То есть вопрос тут такой: почему нельзя писать заведомо понятнее, если это ничего не стоит?
Добавлю. Частенько использую ghci в виде навороченного калькулятора. Ну и после перехода на 7.10, уже немало поправил и перекомпилировал всяких вычислятельных скриптиков. Я вообще не заметил перехода на новую версию. _ВООБЩЕ_ не заметил, понятно? То есть, не то, что мне там запросто высматривать новые сигнатуры ивсётакое. А узнал о том, что в прелюде произошли такие вот изменения уже после того, как у меня уже давно использовался 7.10! Хотя и может быть такое, наверное, что заглядывал в документацию прелюды и просто не обратил внимание на изменения...
Короче говоря, абстрактно рассуждать тут не получится, эти вещи и так понятны, чо с ними спорить. А конкретно — ну точно не на этих примерах надо обсуждать. Может, и найдётся сколько-то прилюдных функций, которые трудновато разобрать в связи с наступленем изменений, но их точно будет немного. Да и сомневаюсь, что такие вообще найдутся.
Я его частично понимаю. При обучении это мозг взорвёт. Нужен какой-то промежуточный язык для обучения. Но... изменение кажется нужным. Геморрой при рефакторинге "List a -> Set a" и т.п. весьма достал.
А мне вот, наоборот, кажется, что нубам полегче будет. В джавах и дотнетах коллекции как раз через интерфейсы доступны, которые типа IEnumerable или как там их — здесь, по-сути, аналогично сделали.
no subject
Date: 2015-10-13 03:15 pm (UTC)no subject
Date: 2015-10-13 04:09 pm (UTC)no subject
Date: 2015-10-13 04:36 pm (UTC)По той же причине в джаве не было функций и до сих пор нет туплов (даже пар). Народу сложно.
no subject
Date: 2015-10-13 05:04 pm (UTC)no subject
Date: 2015-10-13 03:16 pm (UTC)no subject
Date: 2015-10-13 04:12 pm (UTC)no subject
Date: 2015-10-13 04:22 pm (UTC)no subject
Date: 2015-10-13 05:31 pm (UTC)no subject
Date: 2015-10-15 05:04 am (UTC)mapM :: (Traversable traversable, Monad monad) => (a -> monad b) -> traversable a -> monad (traversable b)
вместо
mapM :: (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b)
то ни у кого никаких проблем бы никогда не возникло.
no subject
Date: 2015-10-15 06:53 am (UTC)no subject
Date: 2015-10-15 07:06 am (UTC)type Optical p q f s t a b = p a (f b) -> q s (f t)
type Over p f s t a b = Optical p (->) f s t a b
type Optical' p q f s a = Optical p q f s s a a
type Optical' p q f s a = Simple (Optical p q f) s a
type Optic p f s t a b = p a (f b) -> p s (f t)
no subject
Date: 2015-10-15 07:09 am (UTC)FooBar fooBar = new FooBar - это перебор и копипаста
В твоём примере я вижу
Fnordfstab !no subject
Date: 2015-10-15 07:18 am (UTC)В случае всяких "and" всё куда проще, впрочем, как и в примере от Valentin Budaev.
Тем более, что
(Traversable t, Monad m) =>
это уже вполне так себе документация.
Ну не стопицот буковок же там стоит?
no subject
Date: 2015-10-15 07:29 am (UTC)> (Traversable t, Monad m) =>
> это уже вполне так себе документация.
Вот именно. Без этого куска документации я не могу распарсить (a -> m b) -> t a -> m (t b), а (a -> monad b) -> traversable a -> monad (traversable b) - могу, без проблем.
Более того, штука вся в том, что в случае (a -> m b) -> t a -> m (t b) все равно при чтении это обязательно переводится в (a -> monad b) -> traversable a -> monad (traversable b) в уме, вопрос:
зачем заставлять читателя каждый раз заниматься разбором и запоминанием документации, а потом переводом?
Проблема не в сложности типа, он простой. Проблема в излишней когнитивной нагрузке, которая ложится на читателя, отбитому лень напечатать три лишних буквы, он печатать не будет и оставит читателю догадываться из контекста. Точно также можно не печатать пробелы, ну патаму шта лень, а и без пробелов же текст понятен? Тест не становится сложнее, это по факту тот же текст с тем же смыслом, просто без пробелов. Но его понимание будет требовать _значительно_ больших когнитивных усилий.
Есть и еще один момент: короткосрочная память не в состоянии сколько-нибудь эффективно работать более чем с полдесятком объектов. Следствие: если в строке кода более чем пара подобных обобщенных ф-й, то вы проиграли, задача "мгновенного" парсинга кода лежит за физиологическими пределами человеческого мозга, у вас кешмисс.Надо тратить время на сброк информации в л2 кеш, а потом парсить с обращением к нему - что, конечно, дороже.
> FooBar fooBar = new FooBar - это перебор и копипаста
Никто и не спорит. Но здесь не требуется подстановка, в отличии от примера с типом. А подстановка - очень дорогая для человеческого мозга операция.
no subject
Date: 2015-10-15 07:40 am (UTC)То есть, обсуждать бесполезно.
Вон как для GHC замечательно поступили — проголосовали!
> зачем заставлять читателя каждый раз заниматься
> разбором и запоминанием документации, а потом переводом?
Ну не канает эта аргументация в случае "and" и всякого прилюдного, собственно, о чём и речь в посте.
А для более других примеров — очень может быть, что и соглашусь.
> строке кода более чем пара подобных обобщенных ф-й
"Подобных", это значит, что речь таки идёт о теме поста?
Ну тогда ерунда это.
Я вот оочень быстро привык уголком глаза на такое смотреть.
Только чууточку сложнее. чем со списками получается.
Да и часто ли люди смотрят на тип and?? ;-)
Только в справочных целях.
Вот что ошибки вывода типов усложняются, это уже более существенно, но об этом речи не идёт.
no subject
Date: 2015-10-15 08:03 am (UTC)Поясните, почему не канает. Я так понял, подразумевается, что какой-нибудь mapM - это стандартная библиотека, с-но, вам и не надо парсить все эти траверсаблы и вы даже не заметите, а если заметите - то надо бы привыкнуть, ведь это все-таки стандартная библиотека? Но ведь подобный обобщенный стиль стимулирует и вас свои ф-и писать в таком же обобщенном стиле, то есть если ваша ф-я раньше использовала mapM и принимала List, то теперь вы ее напишете принимающей Traversable. Или вы Имели ввиду что-то другое?
> Да и часто ли люди смотрят на тип and?? ;-)
Я согласен, что если бы это ограничивалось каким-то конечным набором библиотечных ф-й, то все в порядке. Но, см. выше - на практике это будет приводить к тому, что вы будете свои ф-и писать в таком же обобщенном стиле, у вас в коде будут Traversable t => ..., кому-то ваш код надо будет читать. То есть речь не о ф-ях прелюдии, речь о ф-ях пользователей.
Подобная подстановка в любом случае требует дополнительных усилий (с этим, думаю, вы спорить не будете). Другое дело, что вы уже можете заучить, что m - это Monad, t - Traversible и т.д., с-но вы при виде (Traversable t, Monad m) => (a -> m b) -> t a -> m (t b) никаким парсингом не занимаетесь, на часть (Traversable t, Monad m) по сути и не смотрите, а сразу же читаете (a -> m b) -> t a -> m (t b) как оно есть. Вопрос задротства, вобщем-то, но я не считаю, что писать код, полагаясь на то, что ваш читатель в подкорке уже заучил, что t = Traversible - хорошая идея. Вообще, здесь в синтаксисе проблема, и она, к сожалению, не решается.
no subject
Date: 2015-10-15 09:20 am (UTC)>> и всякого прилюдного, собственно, о чём и речь в посте.
> Поясните, почему не канает.
Потому, что простые примеры очень, легко охватываются взглядом.
И какая-то сложность в них присутствует только для новичков, но не связана с однобуквенными переменными или в виде слов.
Может быть, там и попадётся что-то 'сложное', но с ходу, не вспоминается.
> а если заметите - то надо бы привыкнуть,
> ведь это все-таки стандартная библиотека?
Нуу, эти рассуждения вообще хоть чего-то стоят только применительно к новичку. Если кто-то хоть поверхностно асилил класс Monad, то уже никаких проблем не будет.
Да в общем-то, никаких проблем нет осилить и Traversable. Любой "Gentle Introduction" содержит достаточно сведений, чтоб это было сделать несложно.
> Но ведь подобный обобщенный стиль стимулирует
> и вас свои ф-и писать в таком же обобщенном стиле,
> то есть если ваша ф-я раньше использовала mapM
> и принимала List, то теперь вы ее
> напишете принимающей Traversable.
Совсем не обязательно.
Моя функция может работать и со списками, например — тип выведется.
Но если понадобится что-то более другое, чем список, то можно просто продолжать работать, не исполняя всяких "танцев с import'ами" (что-то импортировать, что-то нет, что-то qualified, ...), о чём упоминал аффтар в
http://thedeemon.livejournal.com/104785.html?thread=1783377#t1783377
no subject
Date: 2015-10-15 09:43 am (UTC)Я говорю не об абсолютных величинах, а об относительных. Две-три секунды на подстановку - это вроде как "легко охватывается взглядом", но для подобного кода - неоправдано много. И примерно в бесконечность раз больше, чем когда подстановки нет.
> Нуу, эти рассуждения вообще хоть чего-то стоят только применительно к новичку. Если кто-то хоть поверхностно асилил класс Monad, то уже никаких проблем не будет.
Да я согласен, что если речь идет исключительно о стандартной библиотеке - то все равно все привыкнут. Это не проблема.
> Совсем не обязательно.
Обязательно, потому что такое комьюнити. Для хаскеливтосв чем обобщеннее - тем лучше. Если хаскелист может написать траверсабл вместо листа - он пишет траверсабл, а о том, что в его ф-ю ничего кроме списка не прилетит и прилететь by design не может - даже не задумывается.
Именно об этом человек по ссылке из оп-поста и плачется, а не о том, что у mapM или у другой какой-то библиотечной функции чуть-чуть тип поменялся (на это пофиг всем).
Сейчас все бросятся переписывать типы [a] -> Integer на (Traversable t) => t a -> Integer бодро.
no subject
Date: 2015-10-15 05:38 pm (UTC)Стр. 13: для новых вещей люди требуют ХОРОШО ВИДИМЫЙ синтаксис, для привычных вещей - сжатый.
Твой визави просто новичок, и проецирует свои предпочтения на других.
no subject
Date: 2015-10-15 07:44 pm (UTC)no subject
Date: 2015-10-15 10:57 pm (UTC)Сжатый синтаксис - это по определению такой, при котором информация не теряется. В рассматриваемых примерах она теряется как раз - исключается дублирование, а это всегда потеря.
Отсутствие потерь будет только при условии наличия соглашения, что t - это всегда traversable, m - monad и т.д.
Но подобное соглашение невыполнимо в хаскеле.
Можно было бы добавить возможность определять соответствующие сокращения, но пока ее нет - будет то, что по ссылке в первом посте. Потому что, возвращаясь к началу - на хаскеле пишут отбитые люди.
no subject
Date: 2015-10-16 05:07 am (UTC)Я живу в стране, где именно так и пишут - без пробелов. :) Не сказал бы, что сильно мучаются при чтении.
Это я не столько в защиту ваших оппонентов, сколько про слабость примера.
no subject
Date: 2015-10-16 10:50 am (UTC)Естественно - ведь это тот же текст :)
Очевидно, никто не использовал бы систему письменности, которая вызывает реальные трудности при чтении (в условиях достаточно свободной конкуренции она бы быстро отмерла). Как и однобуквенные невнятные обозначения тоже существенных сложностей не вызывают, вопрос в сравнительном удобстве. Конечно, и без пробелов текст легко парсится, и типы с траверсаблами легко парсятся, но только если писать с пробелами - то текст парсится проще. И типы парсятся проще, если в голове их не надо подставлять. Так что многие языки приобрели пробелы как раз в результате эволюции, которая не является необходимой (и так можно было читать не особо напрягаясь), но является желательной (почему бы не упростить еще, если можно?). А вот примеров обратной трансформации я не припомню.
Так что аналогия как раз весьма точная.
То есть вопрос тут такой: почему нельзя писать заведомо понятнее, если это ничего не стоит?
no subject
Date: 2015-10-15 09:27 am (UTC)Частенько использую ghci в виде навороченного калькулятора.
Ну и после перехода на 7.10, уже немало поправил и перекомпилировал всяких вычислятельных скриптиков.
Я вообще не заметил перехода на новую версию.
_ВООБЩЕ_ не заметил, понятно?
То есть, не то, что мне там запросто высматривать новые сигнатуры ивсётакое.
А узнал о том, что в прелюде произошли такие вот изменения уже после того, как у меня уже давно использовался 7.10!
Хотя и может быть такое, наверное, что заглядывал в документацию прелюды и просто не обратил внимание на изменения...
no subject
Date: 2015-10-15 07:43 am (UTC)А конкретно — ну точно не на этих примерах надо обсуждать.
Может, и найдётся сколько-то прилюдных функций, которые трудновато разобрать в связи с наступленем изменений, но их точно будет немного. Да и сомневаюсь, что такие вообще найдутся.
no subject
Date: 2015-12-04 09:41 am (UTC)Походу, нужен code style с правилом, что если где-то есть
function a
нужно в обязательном порядке делать
Type function
, а не Type f. (ну и f a, соответсвеннно)
Часто, очень нехватает этого function вместо f.
no subject
Date: 2015-10-13 04:24 pm (UTC)no subject
Date: 2015-10-13 04:29 pm (UTC)no subject
Date: 2015-10-13 04:58 pm (UTC)no subject
Date: 2015-10-13 09:15 pm (UTC)no subject
Date: 2015-10-13 05:01 pm (UTC)Но... изменение кажется нужным. Геморрой при рефакторинге "List a -> Set a" и т.п. весьма достал.
no subject
Date: 2015-10-13 09:20 pm (UTC)no subject
Date: 2015-10-15 01:56 am (UTC)Также см. https://www.reddit.com/r/haskell/comments/3ojekh/excuse_me_i_think_this_is_my_stop_haskell_platform/cvy40mi