Обновить
17

Пользователь

28
Подписчики
Отправить сообщение
Философские статьи про программирование позволяют увидеть лес за деревьями.
мне кажется, что тут больше говорится о том, что на коленках получаются очень негибкие структуры, и для расширения функционала приходится хорошо попотеть, рефакторизируя код.
Без сомнения, код должен быть логичным, правильным, понятным. Но в первую очередь — он должен дать ответ на поставленный вопрос за наименьшее время.

Думаю правильнее назвать «за наименьшее количество ресурсов», где под ресурсами часто понимают деньги-люди-время — три взаимозависимых параметра.
Ввод-вывод в Хаскеле может осуществляться не только монадами, но и функторами, апликативными фукнторами, стрелками Клейсли. Было бы желание. Ну и сложность задачи тоже влияет.

Да и монады не так страшны. Основную роль там играет функция bind:
bind :: (a -> m b) -> m a -> m b

что означает, что она берёт 2 аргумента — функцию a -> m b, монадное значение m a и возвращает результат m b
)) Если учесть, что у Хаскеля есть легковесные настоящие потоки — параллельно программировать становится невероятно легче
Думаю, что несмотря на название «программируем императивно», линзы ближе к «программируем объектно-ориентированно».
Но, линзы — это всё же не объекты, поэтому говорить о костылях в данном случае неуместно.
В основном человек принимает новое только через что-то знакомое. Поэтому дана попытка показать совершенно новый инструментарий (ранее неизвестный) при помощи аналогий.
Вообще задачи разные бывают. И необходимы разные подходы к разным задачам.
просто бросают изучать функциональные языки намного раньше, чем смогут обнаружить подобные удобные вещи. Имхо
Я подумал, что после этой статьи — habrahabr.ru/post/189712/, ещё одна статья про линзы не помешает
Статья действительно достаточно сложная для понимания в оригинале ((
Переводить картинки — это сложно. Спасибо большое за статью!
старался как мог ))
wiki/Concepts_(C++)

Вот почти та же самая идея для Cи++, что и классы типов для Хаскеля
Автор предлагает, как я понял, экономить место на плоскости.
Хотя почему-то он не догадывается, что обычные биты(ячейки памяти или регистров) обычно на плоскости — прямоугольники, и тоже плотно упакованы.
Если интересно, можно почитать, например тут — trinary.ru
Случаем, вы не пересмотрели рекламы, «где маленькие зверьки заворачивают шоколад в фольгу»?
Однако в реальной жизни, шоколад так не делают.
И элементы памяти тоже так не делают.

P.S. Представил себе, как сотни миллионов 6-гранных элементов памяти одновременно по-миллисекундно переключают мостики. ))
Код на Хаскеле несколько отличается от ООП-шного.
И развитие кода тоже имеет несоответствия.
В основном код излишне общ.
И в большинстве случаев достаточно просто использовать код.
При этом нет нужны во всяких фабриках и фабриках фабрик.
Из-за обобщённости нет необходимости изменять поведение, достаточно дописать функционал.
Если и нужно менять, то в основном, добавляется очень малое количество кода — до нескольких строчек.
Хотя конечно же, если код не оптимальный — изменения могут быть существенными.

Необходимо отметить, на Хаскеле данными могут быть не только данными, а и действиями, или совокупностью.
Скрытый текст
Например, монады — это данные, с которыми можно работать в императивном стиле, стрелки — данные, с которыми можно работать как блок-схемами, линзы — данные, с которыми можно работать как с объектами.

Поэтому на Хаскеле не надо отдельно заниматься данными, отдельно действиями, отдельно архитектурой.

Если интересна именно эволюция кода, советую почитать интересную статью автора библиотеки, где он описывает, что он добавил в неё.
pipes-3.3.0:…
отрывок
pipes-2.4 впервые идентифицировал существование трёх дополнительных категорий, два из которых я назвал «request» и «respond». Эти категории очень полезны, особенное, если можно использовать ListT с обоими. Но я открыл, что нельзя использовать (/>/) и (\>\) композиции операторов для некоторых прокси-траснформеров, особенно
MaybeP
EitherP
StateP
WriterP
Это очень разочаровывало и казалось действительно странным, что прокси-трансформер может поднять одинаковость этих категорий (т.е. request и respond), но не всегда может поднять соответственную им композицию операторов.
Я принял временное решение, отделить (/>/) и (\>\) в отдельный ListT класс типов.

(работая с pipes-directory и ExceptionP обнаружилось), ExceptionP — это всего лишь синоним EitherP, а EitherP не имплементировал ListT класс, а это означало, что я не мог использовать монаду ProduceT. Поэтому я пересмотрел EitherP и открыл, что есть закон, по которому можно сделать инстанс EitherP для ListT, тот, который я искал ранее. Более того, я мог использовать то же самое для применения MaybeP к ListT.
А это означало, что только 2 прокси-трансформера остались без импементирования ListT:
StateP
WriterP
Кроме того, WriterP внутренне определялся под полом через StateP, означая, что если я смогу найти решение по StateP, я смогу объединить ListT назад к Proxy классу.
Попутно, работая с pipes-parse, я открыл несколько неверных частных случаев для StateP, которые давали неверное поведение. Также оказалось, что и WriterP тоже давал неверное поведение в широких вариантах случаев.
Это означало, что я имплементировал оба этих прокси-трансформера неверно, поскольку оба давали много неверных результатов для многих случаев. И оба этих трансформера не могли быть подключены к ListT.
Это наблюдение позволило мне открыть правильное решение: разрешить StateP и WriterP делится эффектами глобально в линии (pipeline), вместо локально.
Это решение фиксировало обе проблемы:
— оба могли имплементировать List и подчинялись законам ListT
— Оба давали правильное поведение во всех частных случаях.
Вследствие этого, я снова объединил ListT к классу Proxy и объединил request и respond к их соответствующим композитным операторам.
Ну, и сейчас все прокси-трансформеры поднимают все четыре категории верно.
Да, это наиболее близко.
Разница заключается в доступе изменения данных.
Интерфейсы дают доступ лишь к прописанным(в интерфейсе) полям, а инстансы — ко всем полям.

Пы.Сы. Кстати, в Хаскеле есть свои Генерики. Даже не один, а 3 направления
— Generic
— Template
— Data
Хаскель не объектно-ориентированный язык.
В нём нет объектов вообще.

Покажу пример 1+3+4:

Функция
mechanic :: Movement m => m ->m

instance Movement (Double,Double) where
     move (x, y) = (x + dx, y+dy)

instance Movement FlowerVector where
     move (FlowerVector {..}) = FlowerVector {x = x + dx, y = y + dy, 
                             flower_x = flower_x - dx, flower_y = flower_x - dy,
                             flower = flower}

Можете добавить свои данные. Например, как зависит цвет, форма цветка в зависимости от тех или иных событий.
Можно вообще любые данные обрабатывать, только надо написать экземпляр instance Movement MyData
У нас есть 2 объекта, Механика и Вектор:

1)Более простой вариант — объект Механика, принимающий на вход(сеттер) массив пар чисел, и на выходе(геттер) — новые пересчитанный массив пар чисел.
2)Усложнённый вариант Механики, возвращающий несвязанный массив пар чисел.

Объект Вектора с Хризантемкой:
3)Простой вариант — у каждого Вектора своя хризантема.
4)Усложнённый вариант — при этом хризантема во время движения должна крутиться в противофазно, относительно Вектора, к которому прикреплена.

1+3 можно исправить расширенными методами.
2+3, 1+4 лишь в некоторых случаях можно тоже, но так вряд ли кто будет делать. Будут уже править

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность