• Can I haz? Рассматриваем ФП-паттерн Has
    +3
    Ещё вариант — на верхнем уровне вместо MonadReader использовать голый ReaderT. Сам решил эту задачу так:
    -- Пока всё так же.
    data Config = Config { serverConfig :: ServerConfig, rabbitConfig :: RabbitConfig }
    data RabbitConfig
    data ServerConfig
    
    -- Здесь MonadReader и всё красиво.
    runServer :: (MonadReader ServerConfig m, MonadIO m) => m ()
    runServer = ...
    
    runRabbit :: (MonadReader RabbitConfig m, MonadIO m) => m ()
    runRabbit = ...
    
    -- Здесь ReaderT, делаем потоньше.
    -- withReaderT :: (r' -> r) -> ReaderT r m a -> ReaderT r' m a
    runApp :: (MonadIO m) => ReaderT Config m ()
    runApp = do
      withReaderT serverConfig runServer
      withReaderT rabbitConfig runRabbit
    


    Минус — не можем использовать MonadReader наверху, плюс — меньше boilerplate. У меня подмодули стартуют в одном месте у самого main, так что минус несущественный.
  • Делаем из Vim-а конфетку
    +2
    Literate .vimrc
    Сначала, у меня был один .vimrc to rule them all, но когда плагинов становится больше дюжины, становится сложно отслеживать настройки. Некоторые опции (deoplete) надо было настраивать до загрузки плагинов, некоторые — после. Что-то настраивалось через `let g:...`, что-то через `call plugin#function(...`. Потом я разбил на много файликов, отдельно для каждого плагина и source'ил их из .vimrc — стало легче читать, но сложнее редактировать. С Literate .vimrc стало возможным накидать markdown-якорей по конфигу, заголовков, нумерованных списков, e.t.c., а потом просматривать всё в браузере через markdow-preview.
  • Ethernet, FTP, Telnet, HTTP, Bluetooth — основы анализа трафика. Решение задач на сети с r0от-мi. Часть 1
    0
    Вообще, это не круто выкладывать решения с открытой площадки. Не знаю, на ком они зарабатывают, но проходить таски по гайду — фу.
    Если совсем не идёт, можно попросить совета на форуме/ирке/написать в личку.
  • [ВОЗМОЖНО] СОРМ расшифровывает HTTPS трафик к Mail.ru и ICQ
    +2
    Ещё вариант — активная подмена сертификата и безрассудный пользователь.
  • Как всем пережениться (одно-, дву- и трёхполые браки) с точки зрения математики и почему мужики всегда в выигрыше
    +22
    Я слышал, что в одной вселенной люди умеют решать задачи на логику, не притягивая свои иррациональные идеологические суждения. В этой вселенной люди читают этот абзац так:
    «Докажем, что существует недвудольный граф, в котором нельзя выбрать стабильную комбинацию пар. Пусть его матрица весов выглядит так:
    * 3 2 1
    2 * 3 1
    3 2 * 1
    1 1 1 *
    Тогда мы не можем выбрать пары, стабильные согласно определению выше.»
  • Как развернуть односвязный список на собеседовании
    0
    но по этой же логике вам надо писать тесты на фреймворк тестов.

    Вообще-то надо. Тесты — код первого порядка и должен подчиняться всем требованиям релизного кода: стили, ревью, ограничения на выбор зависимостей (и расширений в случае Хаскеля) и наличие тестов.
    Другое дело, что писать тесты на внешний код — ну такое.
  • Как развернуть односвязный список на собеседовании
    +4
    А можно ссылку на .vimrc?

    А вообще зачётно, в духе постов Aphyr.
  • Статически безопасная динамическая типизация à la Python
    +2
    Так это ж и получается Dyn ctx, который получился в самом конце, разве нет?
    Разве что, можно явно Constraint kind не указывать, тайпчекер выведет.

    Точно, просмотрел.
    Хм, что-то у меня это не очень сработало, тайпчекер всё равно не видит a1, a2 в rhs, даже несмотря на ScopedTypeVariables. Там нет ли того, что можно упоминать только те переменные, которые были объявлены с forall в сигнатуре функции?

    Неаккуратно, написал, сорян:
    {-# LANGUAGE ConstraintKinds #-}
    {-# LANGUAGE GADTs #-}
    {-# LANGUAGE RankNTypes #-}
    {-# LANGUAGE ScopedTypeVariables #-}
    {-# LANGUAGE TypeOperators #-}
    
    import Prelude
    import Data.Typeable
    
    data Wrapper cxt where
      Wrap :: (Typeable a, cxt a) => a -> Wrapper cxt
    
    withDyns :: (forall a. Ord a => a -> a -> b)
             -> (TypeRep -> TypeRep -> b)
             -> Wrapper Ord -> Wrapper Ord -> b
    withDyns f def (Wrap (v1 :: a1)) (Wrap (v2 :: a2)) = case eqT :: Maybe (a1 :~: a2) of
      Nothing -> def (typeOf v1) (typeOf v2)
      Just Refl -> f v1 v2
    
    main :: IO ()
    main = do
      let a = Wrap True
      let b = Wrap False
      let c = Wrap 'a'
      print $ withDyns (\x y -> show $ x `compare` y) (\x y -> show x ++ show y) a b
      print $ withDyns (\x y -> show $ x `compare` y) (\x y -> show x ++ show y) a c
    
    $ runghc main.hs
    "GT"
    "BoolChar"
    

    Добавил TypeOperators, Typeable constraint в Wrapper и поправил тип функции def.

    Вообще, я лично не очень люблю интроспекцию типов, свой код в итоге перегрузил кучей вызовов cast, а потом долго ловил ошибку, вызванную cast'ом функции. Сейчас склоняюсь к мысли, что если пространство возможных типов не слишком велико, то проще работать с большим алгебраическим типом, a la, «data ArrayItem = C Char | I Int | B Bool...». Для работы с динамическими типами нужно крайне тщательно спланировать дизайн, потому что расширять его потом может быть очень мучительно, и нужно очень хорошо понимать, что сделать принципиально возможно, а что нет.
  • Статически безопасная динамическая типизация à la Python
    +2
    Можно немного проще, не добавляя TypeRep в обёртку, при помощи ScopedTypeVariables (не увидел объявления SomeTypeRep, кстати):
    data SomeOrd where
      MkSomeOrd :: Ord a => a -> SomeOrd
    
    withDyns :: (forall a. Ord a => a -> a -> b) ->
                (SomeTypeRep -> SomeTypeRep -> b) ->
                SomeOrd -> SomeOrd -> b
    withDyns f def (SomeOrd (v1 :: a1)) (SomeOrd (v2 :: a2)) = case eqT :: Maybe (a1 :~: a2) of
      Nothing -> def (typeOf v1) (typeOf v2)
      Just Refl -> f v1 v2
    

    Ещё советую посмотреть статью про гетерогенные списки на wiki.haskell, там интересная техника с обёртыванием constraint'а, чтобы не заводить отдельный тип Some для каждого ограничения
    data Wrapper (con :: Constraint) where
        Wrap :: (con a) => a -> Wrapper con
    withDyns :: (forall a. Ord a => a -> a -> b) ->
                (Wrapper Ord -> Wrapper Ord -> b) ->
                SomeOrd -> SomeOrd -> b
    withDyns f def (Wrap (v1 :: a1)) (Wrap (v2 :: a2)) = case eqT :: Maybe (a1 :~: a2) of
      Nothing -> def (typeOf v1) (typeOf v2)
      Just Refl -> f v1 v2
    
  • Тестирование не для начинающих
    +1
    Мне кажется, тут смешали две группы людей: будущие профессионалы-программисты и условные «домохозяйки», которые хотят себе себе сайт-визитку или малинку с чайником связать. Вот для первых тезис «пытаться изучать тестирование плюс что-либо ещё — ошибка» я бы развил в «следовательно они должны начинать с тестирования». Тестирование очень сильно способствует элегантности кода, а правило «тесты — код первого порядка и подчиняются тем же требованиям, что и основной код» способствует элегантности тестов.
    Есть ещё известный эффект, что мотивация сильно падает, если долгое время не видно результата — если стек глубокий, а до hello world'а ещё пилить и пилить. Так вот, если параллельно делать тесты, то эффект сильно слабеет, во всяком случае для меня лично.
  • Реализация словаря в Python
    0
    Спасибо.
    У вас псевдокод во фреймах с подсветкой Питона, после первой кавычки всё зеленеет. Попробуйте поиграть с подсветкой, а лучше поменяйте на честный Питон, все всё поймут :)
  • Исключения в Python теперь считаются анти-паттерном
    0
    Это то что я назвал вторым способом. При этом мы теряем информацию, в каком конкретно вызове произошло исключение и должны поддерживать несколько обработчиков, что затрудняет чтение и добавляет сложности.
  • Исключения в Python теперь считаются анти-паттерном
    0
    Что насчёт такого?
    def foo(a, b, dictionary, host):
        j = divide(a / b)
        l = http.get(host).parseSmth()
        k = dictionary[l]
        m = divide(k / j)
        ...
    

    Здесь у нас могут быть разные исключения — арифметика, сеть, отсутствует ключ. Либо мы вешаем на весь блок «except Exception», либо делаем серию except'ов на каждый тип исключения, либо вешаем персональный try на каждый опасный вызов. Второй и третий способ раздувает код и делает его нелинейным, первый я не приемлю, потому что слишком общий. Монада Result добавляет один декоратор за пределами тела функции и по .unwrap() в конец каждой строки.
    Вторая проблема — два опасных divide в одной функции. Допустим мы поставили общий «except ZeroDivisionError», но теперь мы не знаем, какой из них бросил исключение. Монада Result позволяет перед вызовом unwrap() сделать rescue() и добавить подробное описание.
  • Исключения в Python теперь считаются анти-паттерном
    0
    Если я правильно понял — завернуть всё в pipeline и везде где мы получили эти переменные j, l, n, k, z получать их unwrap'ом. Тогда в самих переменных будут честные int'ы, но если хотя бы одна завалится, то pipeline тормознёт вычисления.
  • Исключения в Python теперь считаются анти-паттерном
    0
    В Haskell есть какая-то похожая штука для неявной работы с контейнерами? inline-разворачивания, так сказать?

    Конечно — трансформеры монад. Делаем всякие разные грязные действия, возвращающие Either (Result в статье), если хотя бы одно вернёт Left (Failure), игнорируем все последующие и возращаем этот Left. При этом локальные присваивания игнорируют Either (Result) и всегда думают, что им вернули Right (Success). Если не вернули — смотри выше.
  • Всегда ли нужны Docker, микросервисы и реактивное программирование?
    0
    Вроде бы и да, но в этой статье я вижу другой смысл. В RP коллбеки очень тонкие и не порождают новые коллбеки (они могут, но это не идиоматично). Их задача — получить сообщение и послать его в граф. В статье описывается функция которая занимается вычислениями, выводом и вводом, хотя в RP все три части разделены.
  • Всегда ли нужны Docker, микросервисы и реактивное программирование?
    +10
    Как такой же фрагмент кода будет работать в реактивном стиле? Нить исполняет вычисления, посылает HTTP-запрос и вместо того чтобы заблокироваться и при получении результата синхронно обработать его, описывает код (оставляет callback) который должен быть исполнен в качестве реакции (отсюда слово реактивный) на результат. После этого нить продолжает работу, делая какие-то другие вычисления (может быть, как раз обрабатывая результаты других HTTP-запросов) без переключения контекста.

    Это не реактивное, а асинхронное программирование на коллбеках. Хотя реактивные фреймворки зачастую имеют асинхронный реактор, но одной из фич реактивного программирования является как раз избегание коллбэков. Реактивное программирование — это прежде всего про потоки данных внутри системы и распространение изменений. Никаких отложенных вызовов не предполагается. За манифест спасибо, посмотрю.
  • Что если разделение прибыли 30/70 перестанет быть стандартом геймдева?
    +1
    Пришла мысль, что геймдев идёт по стопам музыкальной и писательской индустрии. Огромное количество авторов, магазины/лейблы/издательства. Всё те же плюсы и минусы: и снижение порога входа и жадные издатели и огромное количество мусора. Жаловаться бессмысленно, зато можно предугадать некоторые будущие шаги.
  • Software Transactional Memory на Free-монадах
    +2
    Спасибо, Хаскелю, на мой взгляд, очень не хватает материала про то как из <непонятная хрень из алгебры> сделать что-то полезное.
  • Полусинтетический организм с шестью основаниями ДНК теперь умеет размножаться
    +4
    Увы, но из новых аминокислот получить улучшенные органы человека не более просто, чем из новых инструкций процессора получить искусственный интеллект. Слишком много запутанных логических уровней в промежутке.
  • Kaspersky Industrial CTF 2017: семь часов, чтобы вырубить завод
    0
    Все задачки на Forensics во многих ctf?
  • Security Week 44: тихая охота, или Carbanak в помощь, зачем Firefox функции Tor Browser, лазейка в Google-«баганайзер»
    +5
    Алекс нашел способ при помощи Java-скрипта (через POST-запрос)

    Скрипта на Jave? Javascript'а?
  • Kaspersky Industrial CTF 2017: семь часов, чтобы вырубить завод
    –1
    habrahabr.ru/company/pt/blog/329984
    А вообще такого рода соревнования тяжело сбалансировать. На короткой дистанции у защитников обычно огромное преимущество, и оргам приходится их по-разному ограничивать.
  • Веб-уязвимости XSLT: Server Side Injection
    +1
    Не, ну за минус я не смолчу: адаптирован == переведён, мало ли что там напереводили иные редакторы GT. Насчёт расширен — можете ткнуть в конкретный кусок, которого нет в оригинальной статье? Если что, вторая табличка — это урезанная версия из pdf'ки с owasp, на которую референс в конце. Пока что я вижу именно что перевод оригинальной статьи с выкинутыми введением и тремя экранами в конце.
  • Веб-уязвимости XSLT: Server Side Injection
    +1
  • Онлайн-квест от MBLTdev. Призы от JetBrains
    0
    Последний довольно очевидный, но четвёртый — это ппц, конечно. Ждём раскрытия через неделю.
  • Нет, жалеть всех сразу не получится
    +3
    Исследования подтверждают, что люди могут накачивать свои «моральные мускулы» и размывать грань между своими и чужими.

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

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

    Если вы боитесь растолстеть, то выпивайте 50г коньяка перед приёмом пищи — алкоголь притупляет страх. Такой подход полностью оправдывает «ложь во спасение». Какой-то извращённый консеквенциализм. Хотя выше было корректно, не про эмоции, а про внешний мир:
    К примеру, мы можем оправдать с моральной точки зрения прослушивание телефона, если стоимость вмешательства в личную жизнь оправдывается преимуществами предотвращения террористической атаки с некоей минимальной частотой, допустим, раз в пять лет.

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

    Удивительно, в чём же может быть причина? Хм, может в разнице освещённости в прессе? Да не, бред какой-то.
  • Нестандартный подход к построению современного языка программирования
    +1
    Ага, я так надеялся увидеть новую абстракцию «наборы», а тут полстатьи про то чем «me» лучше «this». В итоге автор убрал два символа из в общем-то нечасто используемого символа, зато навалил фигурных скобок вместо отступов. Хотя это всё имеет мало отношения к читаемости языка. Плюсы сложнее питона не из-за фигурных скобок.
  • Физика времени: Флэш, суперспособности и релятивистское замедление времени
    0
    «Но причем здесь относительность? Для этого остановимся на минуту и ответим на один вопрос: «Какая сейчас у меня скорость движения?».
    «Ноль» ответите вы и будете правы, если сидите или стоите, но в то же время верным ответом будет и «1679 км/ч», если представим, что вы находитесь в районе устья Амазонки, потому что это скорость вращения земли в районе экватора.»

    Что? Не учитывая движение литосферных плит, любая приколоченная к Земле точка неподвижна относительно меня сейчас.
  • Прячется ли жизнь в тёмной материи?
    0
    Меня вот интересует — не может ли притяжение, вызванное «тёмной материей», оказаться притяжением, вызванным обычной материей но в другом времени? Гравитация же вроде бы одинакова для всех измерений, почему я не могу притягивать самого себя из прошлого/будущего?
  • Getsploit: поиск и загрузка эксплойтов по агрегированной базе данных
    0
    Раз уж на то пошло, то лучше ещё python2/python3 сразу указывать, потому что в разных дистрах всё ещё разная дефолтная версия.
  • Типизируя техническое интервью
    +1
    Вообще-то, подобный код — идеал к которому стремятся хаскеллисты. Почти любой туториал по GADT начинается с чего-нибудь типа «давайте сделаем списки, для которых `head empty` валился бы на этапе компиляции». Если повникать в алгебраическую систему типов, потихоньку начинаешь понимать такие штуки. Зачем обрабатывать исключения в рантайме, если можно сделать неверный код просто некомпилируемым?
  • Конкурентность: Параллелизм
    0
    «Нет» — слишком категорично, я написал определение «для чего», а вы — «как», оба могут быть верными.
    Не могли бы вы пояснить эту мысль?

    В чистом (в смысле функционального программирования) FRP состояние передаётся в качестве ещё одного аргумента вместе с нашим горизонтальным временем. На выходе соответственно получаем ответ и изменённый state. Профит в том, что прошлое не задерживается в графе, что сильно упрощает последующую отладку.
    А где-то в глубине — обычный event-loop, дёргающий FRP граф, когда срабатывает poll. Я бы это не называл «способ организации кода», всё-таки это про проектирование, а не про написание кода.
  • Конкурентность: Параллелизм
    –1
    Такое же как и остальное перечисленное — это ещё один паттерн. В отличие от параллельного программирования, асинхронное требует всего один механизм на уровне системных вызовов — select, poll, epoll или ещё что. Все перечисленные неявно его используют, разница только на верхнем уровне.
    Отвечая на сам вопрос: FRP — это stateless способ выбрать ответ на пришедший запрос в реальном времени.
  • Конкурентность: Параллелизм
    0
    В асинхронности ещё можно поговорить о ново-(старо-)модном Functional Reactive Programming. Более требовательный к дизайну, зато на разработке не будет боли с callback hell.

    P.S. Таки конкурентность != парелеллизм. Это всё таки о целях, а не о реализации.
  • Доступен удобный браузер для выхода в сеть I2P
    0
    TorBrowser + FoxyProxy + i2p router. Всего-то прописать несколько правил. Я роутер вообще держу на vpn'ке, чтобы аптайм не терять.
  • Поисковый риск или как Google почти убил ProtonMail
    0
    http://nigma.ru/
    Нигма живёт и не чахнет, особо редкие вещи в ней ищу потому что фильтры.
  • Как найти поддомены за считанные минуты?
    0
    Кстати ещё классика — это google hacking (урлы, содержащие example.com, но не содержащие www.example.com, их иногда забывают в robots.txt поставить). И ещё мне как-то приходилось находить поддомен через comodo dns сервер, который не был зареган на 8.8.8.8 и 208.67.222.222.
  • Как найти поддомены за считанные минуты?
    +1
    Иногда да, а иногда там *.example.com. Насколько я понимаю поиск поддоменов всё равно сводится к пауку и/или перебору по словарю.
  • Разбор задач первого этапа отбора в школу программистов HeadHunter 2016
    0
    Задача 3: интересный факт, дроби n/7 имеют периоды (7-1) в десятичной записи и они получаются перестановкой цифр для разных n. Если не ошибаюсь, то же верно и для 17 с периодом (17-1). Короче, увлекающиеся подобной фигнёй решают эту задачу в уме.