Pull to refresh
-1
1.8

Специалист по теории типов USB-кабелей

Send message

Всмысле перевести? Мне функцию дали. По условию. Где сигнатура?

А тут вам в условии дали фору: сигнатуру можете выбрать как вам удобнее.

Если по своему, то во-первых, возвращение NetworkError - чушь собачья. При живых эксепшенах.

Это чтобы потом вместо того, чтоб просто посмотреть на тип функции, ходить спрашивать «а что функция кидает?», как вы уже сделали выше?

Но, впрочем, я и про это написал! Во:

Но если вам удобнее с исключениями, то можете и с исключениями, конечно, но тогда вам придётся отобрать те, которые соответствуют только NetworkError, и собрать их все.

Во-вторых, запрос коммента по сети по одному - чушь собачья.

Вы реально по кругу ходите. Мы с вами это уже обсудили.

Например ошибка кредов - вот зачем дальше выбирать эти комменты?

Вы точно не понимаете, что такое модельная задача.

Решите уже эту, наконец, и обсудим границы применимости, усложнения и прочее.

Никак. Это не хаскель.

ФП что-то быстро сдулось. А аналог уже даже в плюсы завезли в виде std::expected.

И шарп статически типизированный. Там нельзя инт поменять на коммент.

Ну хаскель-то известен своей динамической типизацией, конечно.

В данном случае это значит «вернуть такое же по форме дерево, но в котором на данной позиции вместо инта лежит соответствующий этому инту комментарий». Сорян за функциональный жаргон.

Мы разные вещи понимаем под работой.

Будь по вашему, никто бы в здравом умен не пилил бы опенсорц.

Юзабельный опенсорс (ядро линукса, llvm, и так далее) пишут люди за зарплату. Скажем 80% контрибьюторов в ядро — корпы, это тупо по емейлам видно.

А хобби-опенсорс уровня «сделал пердюльку для себя и выложил в гитхаб» — это не работа.

Я на шарпе пишу, нахер мне сигнатура хаскеля?

Чтобы перевести её на шарп так, как вы считаете наиболее идиоматичным. Я на шарпе не писатель, только читатель, и так как вы говорили, что используете ФП в шарпе (следовательно, знакомы с концепциями) и не переносите синтаксис хаскеля (следовательно, знакомы с ним), мне представляется разумным предположить, что вы её прочитать и перевести сможете.

Впрочем, возможную сигнатуру шарпа я тоже приводил выше.

У шарпа есть тип возвращаемого значения. Входит в сигнатуру функции.

Пока ничего нового, всё как на хаскеле.

Там ещё входные параметры, но допустим на входе int id. Какой тип возвращаемого значения?

У загружатора одного комментария? Либо NetworkError, либо Comment. Как выражается «либо» в шарпе идиоматически, я не знаю. В хаскеле это Either.

Сигнатура какая у функции?

Вы по кругу просто ходите, что ли? Сигнатуру я уже тоже выше писал:

loadComment :: Int -> IO (Either NetworkError Comment)

Чтобы два раза не вставать. Int нельзя заменить на строку. И на Comment тоже.

Не понял. Кто запретил?

GHCi, version 9.12.2: https://www.haskell.org/ghc/  :? for help
λ> import Data.Tree
λ> t = Node 10 [Node 20 [], Node 30 []]
λ> :t t
t :: Num a => Tree a
λ> :t fmap show t
fmap show t :: Tree String
λ> fmap show t
Node {rootLabel = "10", subForest = [Node {rootLabel = "20", subForest = []},Node {rootLabel = "30", subForest = []}]}

Вот я вам заменил число на строку.

Неправильно. Давайте ещё раз

Что именно неправильно-то?

А, чисто для протокола — на исключения можете забить и считать, что их нет. Но если вам удобнее с исключениями, то можете и с исключениями, конечно, но тогда вам придётся отобрать те, которые соответствуют только NetworkError, и собрать их все.

Полный формат функции. Что принимает, что выдаёт, чем кидается.

В типах же описано! Принимает Int, выдаёт либо объект типа NetworkError (дан свыше), либо объект типа Comment (тоже).

Вам нужно получить Tree Int (дерево с интами в узлах), для каждого инта загрузить комментарий через loadComment, и выдать либо список возникших ошибок (если возникла хотя бы одна), либо дерево, где каждый Int заменён на соответствующий комментарий.

Я очень рад, но проект на 5к строк нельзя назвать большим. И средне-большим. И даже средним. Никак.

Так а проект на 50к строк можно назвать средним?

И скажите, какой апи для получения комментов.

Функция loadComment. Пришла из васиной библиотеки, которую он написал для работы со своим сервисом.

Если это какой-то бекенд, то давайте сначала ПОЛНЫЙ текст на хаскеле обработки апи. Вместе с загрузкой дерева, вместе с отправкой комментов. Вместе с сериализацией. А потом будем сравнивать именно полный текст.

Вы не понимаете, что такое модельная задача. Ну ок.

Я так и сделал.

Нет, не сделали, потому что нет законченного кода, используемого данную вам loadComment из васиной библиотеки и любой удобный вам тип данных для представления деревьев.

В чём проблема? Вы даже не потрудились сказать, где может ошибка возникнуть.

В функции loadComment, как это было ясно из её типа.

Потому что там нет места функциональщине. Там выключен Нейгл и включено на максимум байтоёбство.

Оххх бро…

Сколько раз я занимался байтоёбством на хаскеле и получал код, работающий на уровне плюсов (а иногда чутка быстрее) — не перечесть. В худшем случае объём вычислительного кода сравним с объёмом кода на плюсах.

Да, ещё раз скажу. 5000 строк - это даже не маленький проект. Это крохотный. Не надо говорить, что хаскель компактный. Это не так.

Он делал больше, чем реализация соседней группы, делавшей ту же задачу на плюсах, которую до меня припрягли делать то же, которая делала это втроём, которая делала это пару лет (я справился за пару месяцев чистого времени как сайд-проект), и которая это в итоге так и не доделала до конца. Сколько там строк кода было точно, я не знаю, но точно больше нескольких десятков тысяч.

А как вы там древообразные структуры представляете, что у вас там в стандартной библиотеке для этого есть? (ведь есть же? выразительный же язык, удобный?)

Ну вот так и представьте. У вас полная свобода, делайте как вам удобнее. Только, ну, чтобы дерево, конечно. Я не знаю C# достаточно хорошо (и вообще только читать на нём могу, считайте), чтобы вас ограничивать написанием структуры за вас.

На плюсах я бы предположил, что где-то ещё написано что-то вроде

template<typename V>
struct Tree
{
  V value;
  std::vector<Tree<V>> children;
};

а как там на шарпе — я хз.

А в чём минусы? Хотите — работаете в стартапе. Не хотите — работаете в крупной корпорации, четыре часа в день надувая щёки на митингах, ещё два часа ходя за кофе/социализацией/етц, и ещё два что-то вяло кодируя. Хотите чего-то ещё — идёте в такую компанию.

Капитализм — это выбор. Не вижу проблем.

Вы ведь не понимаете, что такое модельная задача, да?

Я уже написал выше, нахрена. Например:

Вам API'шку дали, которая не умеет в запрос всех комментариев сразу, надо долбить по одному.

— и да, такие случаи бывали на практике. Сервис, реализующий апишку, чужой, а вы работаете в крупной копрорации, где добавление батчинга в чужой сервис займёт пару месяцев, а фичу неплохо бы деливерить поскорее. «$lang применим только к академически чистым ситуациям» шутят обычно как раз при $lang ≔ haskell, и получается смешно (метасмешно?), когда таким языком, похоже, оказывается C#.

Или, например:

Это, например, и backtracking-решение систем констрейнтов

где аналога «грузить все комменты сразу» просто нет.

Но вы уже третий комментарий уворачиваетесь от того, чтобы просто написать код на выразительном сишарпе, что, похоже, должно занять у вас меньше пяти минут (а на обсуждение, почему этого делать не надо, вы уже точно потратили больше). Кажется, что-то здесь нечисто!

У вас условие притянуто за уши к функциональщине.

У меня условие притянуто за уши к реальным задачам, которые приходится решать.

Причём это не только работа с тупыми апишками. Это, например, и backtracking-решение систем констрейнтов, но задачу в терминах апишек поймёт больше людей.

Ошибки так не ловятся. Сове больно и обидно. Вы хотите что-то поймать, но сами не знаете, что и зачем.

Почему не знаю? Знаю! Вон в типе функции написано, что она может дать NetworkError. А у вас в типе функции что написано? А ничего не написано, потому что и функции нет, есть какие-то обрывки кода, демонстрирующие LINQ.

Если надо задачку решить шарпом - не сомневайтесь, я её смогу решить.

Ну так решите уже, наконец, тем более, что по вашим словам это очень просто! Ещё раз на всякий: вам дан тип деревьев из стандартной библиотеки, и у вас есть функция загрузки одного комментария (её Вася написал, не вы), на C# будет выглядеть как-то так, наверное (не знаю, что у вас там вместо Either принято):

Either<NetworkError, Comment> LoadComment(int id);

Вам нужно написать функцию, которая проходит по дереву интов, пытается все комменты, и либо возвращает дерево, где в узле вместо инта — коммент, либо список ошибок загрузки.

Всё равно меньше по строкам будет, чем у вас.

У меня будет одна строка на тип функции и одна-две строки на реализацию. Всё. У вас уже больше.

Структура на месте, ошибки наверху ловятся.

На каком верху? Где у вас все ошибки собираются в случае, если появляется хотя бы одна? Где это поведение видно в типах?

И я вам скажу, что ваш код нихрена не делает.

Использование в будущем времени слов «код, который я вам покажу» вам ни на что не намекает? Мой код — это условие задачи. Что дано. И парсинг ошибок, например, происходит в функции загрузки комментария.

Я просто не хочу портить своей непонятной функциональщиной ваш чистый сишарп — покажите ваше решение вы, и я потом покажу своё.

И да, я специально не стал отлавливать ошибки.

Выкинуть половину условия задачи и говорить, что сделали это специально — довольно странный флекс, но окей.

Но ошибки надо понимать, где могут возникнуть.

Они могут возникнуть при сетевом запросе. Где вы этот запрос делаете, кстати — не видно.

У меня запрос комментов идёт одним селектом в "IN" синтаксисе

Нельзя так. Вам API'шку дали, которая не умеет в запрос всех комментариев сразу, надо долбить по одному.

[...] Потом запрос:

Итого ошибки вы не обрабатываете, древообразную структуру комментариев потеряли, и, судя по форме запроса, потеряли даже порядок комментариев.

Можете всё-таки написать одну функцию целиком, которая это всё делает?

И при всём этом

Но в шарпе даже меньше строк.

неверно, потому что код, который я вам покажу, когда вы всё-таки сделаете плюс-минус что-то, соответствующее предложенной задачке, будет иметь меньше строк, чем у вас уже написано.

И для меня синтаксис хаскеля выглядит типичной ФП-сплющенной чёрной магией, где за смысл отвечают знаки препинания, а не слова.

Конечно, куда лучше, когда знаки препинания не отвечают вообще ни за что, зато(везде(понатыканы<(разные<скобочки>)>)), которые не несут вообще никакой смысловой нагрузки и являются просто визуальным шумом. Да и IEnumerable<int> читать куда проще, чем [Int]! Правда, создавать одноэлементный список всё равно приходится через [], но неважно.

Кстати,

У нас хвостовая рекурсия и discrimination unit, судя по всему.

хвостовой рекурсии здесь нет (и при обходе дерева быть не может, кажется, но мне лень это доказывать), а discriminated union из одного конструктора — это просто класс/структура, если в ваших терминах.

В шарпе
C#

Мой исходный тезис был про плюсы, и конкретно этот пример был про то, что во втором случае надо знать, что такое accumulate, но код при этом проще. Но неважно, продолжим.

В шарпе я постоянно пользуюсь такими вещами, как Sum(i => vec[i]), Select/SelectMany, цепочки функций и другие элементы ФП.

Основной элемент ФП последние лет 15-20 — это выразительные типы (и про типы я писал в предыдущем комментарии). Глядя на один лишь тип функции на хаскеле, я знаю сильно больше, что она не может делать (при некоторых естественных дополнительных предположениях), чем в шарпе или в плюсах (а в последних версиях — что она обязана делать). И именно это сильно помогает читать код и поддерживать средние и большие проекты.

Так что в данном случае шарп с хаскелем будет 1:1.

Окей, моё любимое упражнение. У вас есть дерево с интами и функция, которая по инту-айдишнику загружает по сети, скажем, комментарий с этим айди (ну или возвращает ошибку). Можете написать код на шарпе, который проходит по дереву, загружает эти комментарии, и либо собирает все ошибки (если была хотя бы одна), либо отдаёт дерево комментариев?

На хаскеле данное по условию выглядит как

data Tree a = Node
  { value :: a
  , children :: [Tree a]
  }

loadComment :: Int -> IO (Either NetworkError Comment)

— на C# переведите по вашему усмотрению.

У крестов есть мощная система шаблонов и если по шаблонам упороться, можно оставить любой фп язык позади без вариантов вообще.

Я по шаблонам упарываюсь профессионально за деньги. Так вот, это — унылое костыльное подобие, в зависимости от конкретного применения, одного из:

  • нормального параметрического полиморфизма (есть в любом современном ФП-языке из ML-семейства)

  • метапрограммирования а-ля haskell generics или template haskell

  • попыток считать что-то на типах а-ля type families или зависимые типы в идрисе.

(и именно потому, что это костыльное подобие, за знание шаблонов C++ готовы платить сильно больше — правда, ощущаешь себя при этом экзотической проституткой с широким спектром услуг, не более)

Учитывая особенности плюсов, весь код с темплейтами должен быть в хедерах (если упрощать, опять же — частные случаи явного инстанциирования мы не обсуждаем), что делает их использование для DI или для гарантирования инвариантов запретительным для реальных проектов. Ну или, если очень надо, то одно TU компилируется по несколько минут (что действительно больше, чем ФП-языки, но не по тем метрикам, по которым хотелось бы).

Тайпклассы + type families + GADT'ы оставляют шаблоны далеко позади.

Только это скорее необходимый минимум, proof-of-concept, чем пример реального проекта.

Это уже какие-то апостериорные фильтры по непонятным критериям.

Proof-of-concept — это компилятор идриса на идрисе (потому что он не умеет ничего, по большому счёту, и потому что ему несколько лет, и пилится он автором языка и полутора энтузиастами). А ghc — это проект, которому уже третий десяток лет, в котором под миллион строчек кода, весьма нетривиальный фронтенд/тайпчекер, очень нетривиальный пайплайн оптимизации, и в котором регулярно допиливаются новые (и часто нетривиальные с точки зрения реализации) фичи языка. В моих определениях это каноничный «большой проект».

Когда в одном языке меньше бойлерплейт конструкций, чем в другом.

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

А когда количество строчек сокращается за счёт повышения когнитивного порога восприятия кода - это плохо. Очень плохо.

Что лучше,

int sum = 0;
for (int i = 0; i < vec.size(); ++i)
  sum += vec[i];

или

const int sum = accumulate(vec, 0);

?

Есть разница между «когнитивным порогом восприятия кода при условии знания идиом языка, которые где-то примерно O(1) с точки зрения сложности изучения от числа проектов» и «когнитивным порогом восприятия кода потому, что код захламлен неважными деталями реализации с неверного уровня абстракции».

И по моему опыту, чем язык чище (в смысле, чем типы у него выразительнее), тем код читать проще. Код на идрисе или агде читать проще, чем на хаскеле, который, в свою очередь, читать проще, чем на окамле, который, в свою очередь, читать проще, чем на плюсах.

Во-первых это совершенно условные 50 тыс строк, которые вы вывели исходя из придуманного коэффициента.

Это основывается на опыте сравнения подобных проектов. Могло бы быть 40 тыщ, могло бы быть 60 — на суть это не влияет на этих масштабах.

50 - средний. А 5к - маленький, как ни крути.

На C++ — маленький. На хаскеле — средний. Потому что предметной сложности в нём будет как в проекте на 50к на плюсах.

Не ожидал увидеть в треде о Scrum и ООП [очередное] обсуждение коммунизма, но [в очередной раз] не могу пройти мимо.

Построенная чисто на рыночных принципах медицина в США

Медицина в США перестала быть чисто рыночной где-то между 1950-ми и 1970-ми (например, те же CON — очень рыночно), и исход немного предсказуем: количество проедающих деньги бюрократов попёрло вверх:

а вместе с проедающими деньги бюрократами попёрли вверх и косты:

При этом государственные траты на медицину растут почти так же, как частные:

При этом куда менее регулируемые частные косметические процедуры растут даже меньше инфляции:

хотя количество одних только косметических операций выросло (с 97-го, раньше статистику найти сложнее) в два раза, а всех вмешательств — в шесть раз.

по вполне объективным показателя построенной на социалистических принципах медицине тех же стран Европы

Не существует объективных показателей, способных сравнить существенно рыночные и существенно нерыночные системы. Вы можете спрашивать, например, «сколько трудового времени нужно потратить человеку из X-перцентиля по доходам для получения такого-то ухода, и как быстро он его получит», и Европа стремится, чтобы для всех X это было примерно одинаковым. Лично мне совершенно неважно, чтобы это было одинаковым, и лично мне важнее, чтобы лично мне услуги были доступны за малое количество моих усилий и быстро.

В США они мне так доступны. В Европе — нет. В Европе я за полтора года не дождался очереди на очки. В Европе одна моя родственница умерла от рака, потому что ждала в очереди на обследование полгода и дождалась до неоперабельной стадии (но да, после постановки диагноза ей бесплатно соцработница носила продукты или чё-т такое). В Европе одна моя знакомая по работе стояла в очереди в больницу по ментальным вопросам, простояла два года, больница закрылась, пришлось перейти в другую больницу и стоять в очередь туда заново. В Европе NHS оценит вашу жизнь и решит, нужно ли вам делать операцию или нет. Или вы суициднитесь, пока будете ждать в очереди. Или будете выдирать сами себе зубы. Или г-во решит, что вам лучше умереть, чем собрать деньги себе на лечение заграницей (и взять государственные), и запретит про это рассказывать. Или вы с супругой выберете эвтаназию вместо того, чтобы ждать очереди в NHS. Или NHS решит, что ребёнку не надо ехать в Италию за лечением, хотя там всё готово, и ребёнок просто сдохнет.

Про канадский хелскер, где для сокращения костов делают эвтаназию (или там умерших в очередях не считают на государственном уровне — так важно государству заботиться о людях) можно даже не вспоминать.

Но да, зато всем всё бесплатно (почти).

Не, спасибо, я лучше с осознаваемой ответственностью за свою жизнь, и в долгах, но живым. И, собсна, про NHS у меня куча ссылок, выше — так, мелкая выборка, и каждый раз, когда я их читаю, я вспоминаю, что коммунисты — не люди, а желающие власти без всякой ответственности упыри, и вспоминаю некоего

Rafał Gan-Ganowicz

When asked how it felt to take human life, I wouldn't know, I've only killed communists.

Банально тратят в разы больше денег и получают заметно худшие результаты типа продолжительности жизни.

Про деньги я уже написал выше, а про продолжительность жизни — на те же фентаниловые смерти [собственный выбор; сильно положительно коррелирует с социальностью штата] и ожирение [почти всегда собственный выбор] сделали коррекцию? Я коррекцию делал, и учёт одних только фентаниловых смертей резко бампал продолжительность жизни в Штатах на несколько лет.

Есть очень хороший показатель эффективности хелскера: отношение cancer incidence rate и cancer death rate. Вы хотите, чтобы это отношение было выше: тогда больше рака выявляется, и меньше людей от него умирает. И, сюрприз, США и тут впереди (если сравнить с Канадой, Францией и Германией, например) в полтора-два раза:

  • US: 367 / 181 = 2.03

  • Germany: 274 / 301 = 0.9

  • France: 339 / 288 = 1.17

  • Canada: 345 / 257 = 1.34

Организовывать работу полиции и армии по рыночным принципам по моему не пытается уже никто вообще в мире.

Лучший подход к полиции — это вооружённое население, конечно. Децентрализовано, рыночно, эффективно.

Да и к армии тоже. Попробуйте это в мичети.

Ну и это уже не говоря о том, что рынок без государственного присмотра практически неизбежно скатывается в монополизацию

Нет, конечно, но мой комментарий уже и так слишком длинный.

А вот ФП-шных проектов, достаточно больших, я что-то не припомню.

Компиляторы ФП-языков написаны на ФП-языках, как минимум, а это достаточно простые проекты. Тот же ghc, например.

Заодно отвечу на соседний комментарий:

Только по прежнему в проде я не вижу больших проектов на чисто фп, вроде F#/scala/haskell.

Регулярно видел большие проекты на хаскеле в проде. И сам делал лично в одну морду, и на последней работе, например, очередной компилятор/тайпчекер на хаскеле был написан, и мы даже начали его формально верифицировать на coq (тоже ФП).

Просто есть тут такой один нюанс… например, был у меня один проект на хаскеле, пять тыщ строк, написан в одиночку по большому счёту. Если бы я его переписал на C++, то там было бы по моим оценкам примерно на порядок больше. Считать ли это «большим» [для одного разработчика] проектом? 50 тыщ строк для одного разраба — это уже средне-большое, как по мне.

Проблема на вашей стороне: мне знакомые ссылки на вк-видео не присылают.

Я пишу «в обсуждаемой статье», вы приводите скриншоты комментариев.

Почему? Вы умственно отсталый, или ориентируетесь, как вы писали, на эмоции умственно отсталых «хомячков», или по каким-то ещё причинам?

Information

Rating
1,578-th
Registered
Activity