Как стать автором
Обновить

Комментарии 41

Посмотреть бы пример проектирования корпоративного ПО, а лучше и прямо бухгалтерского…
Для этого можно было бы наняться в банк Bank of America Merril Lynch. Не совсем бухгалтерия, но все же о деньгах.

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

Слышал звон — не знаю где он
Системы прайсинга и HFT настолько далеки от бухгалтерского ПО, насколько ваша игра от программирования реальной ракеты для полета на Марс. И там и там космос, но на столько разный…
НЛО прилетело и опубликовало эту надпись здесь
Pattern matching, это больше про удобный доступ к составным данным, деструктурирование.
Основная идея ФП, в отсутствии состояний и иммутабельности данных, с этой точки зрения ФП и ООП сильно отличаются.
НЛО прилетело и опубликовало эту надпись здесь
Вы забываете, что в ФП граница между данными и кодом почти отсутствует. Понимая данные как то, что можно паттерн-матчить, вы упускаете возможность создавать, напимер, список функций-мутаторов, который позднее может быть применен к данным, или даже модифицирован в другой список, или даже модифицирован в одну функцию, которая уже и будет работать с данными…
НЛО прилетело и опубликовало эту надпись здесь
Что, простите, является тонкостью дизайна конкретного языка? Каррирование? Или отсутствие границы между кодом и данными? Это неотъемлемая часть Любого ФЯ и лямбда-исчисления. А JS, кстати, весьма «функционален». Я полагаю, разговора с вами не получится, так как вы не разбираетесь в теме.
НЛО прилетело и опубликовало эту надпись здесь
Отсутствие между кодом и данными характерно для Лиспо-подобных языков и для языков семейства ML, к которым относится Haskell.

Функции как данные
module Main where

import System.Random as R
import qualified Data.List as L

alg1 [] = []
alg1 (p:xs) =  alg1 [ x | x <- xs, x < p]
               ++ [p]
               ++ alg1 [x | x <- xs, x >= p ]

alg2 [] = []
alg2 (p:xs) = (alg2 lesser) ++ [p] ++ (alg2 greater)
    where
        lesser  = filter (< p) xs
        greater = filter (>= p) xs
        
quicksorts = [alg1, alg2]

testData = take 10 $ R.randomRs (1, 100) (mkStdGen 10) :: [Int]
expectedData = L.sort testData
test = all (== expectedData) $ map ($ testData) quicksorts

main = do
    putStrLn $ "Test result: " ++ show test
    print $ alg1 testData
    print $ alg2 testData



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

Чтобы разговаривать по существу, необходимо избегать подобных ошибок.
НЛО прилетело и опубликовало эту надпись здесь
Haskell не является динамическим языком, а то, что вы просите, как раз можно сделать только на динамическом языке.

Однако, если вам хочется видеть абстрактное синтаксическое дерево Haskell-кода, можно воспользоваться функциями модуля «Language.Haskell.Parser» из состава «haskell-src», и скормить функции parseModule ваш код.

Либо можно построить quicksort на вычислительном AST, которое потом выполнить самостоятельно. А напечатать AST очень просто.

P.S. Это не спекуляции.
Дано:
Существует множество D (языки с динамической типизацией).
x принадлежит D.
Существует множество F (функциональные языки).
По определению, F != D.

Ваше рассуждение:
«Если для вас весьма функционален JS» -> Предположим, x имеет свойство f (весьма функционален).
«то любой язык с динамической типизацией» -> Следовательно, для любого l из D: l имеет свойство f.
«В действительности они не являются функциональными» -> Противоречие. Все l из D не принадлежат F.

Однако, последнее заключение не является противоречием первому, так как подобного условия не было. Следовательно, последнее заключение не относится к цепочке рассуждений, а значит, не является корректным доказательством.
НЛО прилетело и опубликовало эту надпись здесь
О ссылке: да, лисповая реализация именно такая, а у Haskell иная реализация, и обе имеют право на существование. Но эти две реализации в равной мере иллюстрируют концепцию «code == data», и нет оснований говорить, что существование одной реализации автоматически делает другую ущербной.

Спорить больше не буду.

И да, я сегодня несговорчив, приношу извинения.
Боюсь, что подобная трактовка паттерн-матчинга слишком притянута за уши. И к наследованию не имеет отношения. ФП от ООП действительно отличается. Если не принять это как аксиому, у вас будет получаться снова то же ООП на функциональном языке, только выглядеть и работать будет ужасно. Знаете, в чем еще отличие? В ФП позволительно и даже важно работать с, гм, «недоопределенными» функциями, когда n-Арной функции дадены n-k аргументов. Это ведет к гораздо большей гибкости, нежели любой ООП-механизм. Код получается совершенно иной, с иным дизайном, с другой основопей идеей.
А законыв ФП, действительно, есть, и они о другом.
НЛО прилетело и опубликовало эту надпись здесь
Нет. Цель проектирования — получить результат за приемлемые потраченные ресурсы с приемлемой сложностью поддержки и доработки. А «high cohesion low coupling» — лишь важный способ этого добиться.

Про самообман вы передергиваете. Только что вы присвоили мне придуманную формулировку «списки и кортежи автоматически решат проблемы проектирования» и, как водится, смело с ней разобрались. Этот прием называется «Чучело».

Если бы списки и кортежи решили все мои проблемы, этой статьи бы не было.

А названные принципы нигде и не отвергаются, читайте внимательнее. Вот только их недостаточно для проектирования. Говоря вашими словами, эти принципы не решают автоматически проблемы проектирования.
НЛО прилетело и опубликовало эту надпись здесь
Ваша подозрительность не является аргументом.
Отсутствие этих слов в статье не приравнивает статью автоматически к разряду плохих.
Классические паттерны упоминались, но не назывались поименно.

Хорошая статья о паттернах, действительно, хорошая. Вот только появилась она буквально вчера.

У моей статьи будет продолжение. Но я не предполагаю переносить все или часть классиеских паттернов в мир, где они по большей части не нужны, и к тому же, это уже обсуждалось.
Если бы вы сделали что-то подобное на Haskell, то я бы был первым кто плюсанул вам в карму.

Есть старая, но хорошая и краткая статья:
blog.ezyang.com/2010/05/design-patterns-in-haskel/
НЛО прилетело и опубликовало эту надпись здесь
Я, кажется, понял, откуда у вас такое желание натянуть ООП на Хаскель и другие ФЯ. Ваш опыт родом из Erlang, который сформировал у вас неверное представление об ФП, и вы пытаетесь всё подогнать под это представление. Это неверный подход. ФП имеет с ООП мало общего, и не важно, что в Erlang эти понятия имеют свою реализацию. Вот, например, Scala: и функциональный язык, и ООП-язык; Haskell — чистый функциональный язык; но что Erlang? Ответ вы найдете в статье, которую я нахожу очень точной и правдивой.
На счёт Синглтонов — в Хаскеле это совершенно другое.
Из той ссылки, что вы дали:
Singleton types are a technique for “faking” dependent types in non-dependent languages, such as Haskell. ... A singleton type is a type with exactly one value.
Это типы с единственным значением, а не единственный экземпляр типа.

Согласен, несколько наивная статья, что я дал.
НЛО прилетело и опубликовало эту надпись здесь
Я думаю паттерны тем и хороши, что они не привязаны к языку.

Думаю, правильнее сказать, разные паттерны разной силой привязаны к парадигмам программирования.
Тот же MCV никак не связан с языками и даже парадигмами.

Если мы говорим о Синглтоне, то этот паттерн имеет место в языках с общим пространством данных, где мы хотим получить единственное значение переменной.
Применяя это на Хаскель: возможность иметь Одиночку возможна лишь в монадах состояний State, таких как IO, ST, IORef, STRef. Вне контекста состояний, ни одна функция не делит «общее пространство данных», а значит, шаблон Одиночка бессмысленен вне состояний в Хаскеле.
Сорри, промахнулся уровнем.
Ответил вам чуьть ниже (промахнулся).
Будьте добры, по обмену опытом.
1. Какую конкретно реализацию FRP используете и как она в деле?
2. Я хочу простенький сервер для мультиплейер. Насколько трудоемко набросать на Haskell набело, вместо допиливания warp? Скажем несложный UDP сервер? Ну да, я читал в RWH, но то в книжке. А в деле?
3. Известна доктрина максимально разносить, еще на стадии дизайна, чистую и побочно-эффективную компоненты с целью изжить последнюю. Ваше мнение? Например Michael Snoyman, на мой взгляд, такой подход не разделяет. Yesod просто весь соткан из монад и трансформеров.
4. Persistent? STM это хорошо, но недостаточно. Вы бы рекомендовали природный Acid-State, или кондуктор к чему нибудь более SQL классичному?
Спасибо.
1. Использую Netwire в качестве FRP- основы нечистой части программы. Мне нравятся два аргумента в пользу этой библиотеки: стрелочный интерфейс как вариант, и нацеленность на игры. Из-за последнего, например, там есть работа с таймером. В простых примерах библиотека ведет себя хорошо, пользоваться удобно. Правда, другие я не испытывал, только читал о них.
2. Точно не скажу. Если простенький, без претензий на красивости, то, думаю, пару дней, — при условии, что вы знаете, как работают UDP серверы. У меня ушло бы неделя или около того, но посылающий и принимающий сообщения сервер на коленке можно сделать быстро. Я как-то делал сервер визуализации Хаскелля, там ничего сверъестественного не было в сетевом коде… Разве что я использовал MVar для разделяемого доступа.
3. И да, и нет. Если совсем не разделять, будет обычный императивный код. Но если воспользоваться тем же ФРП, то это будет очень даже хороший код.
4. Шут его знает… Действительно, синхронизироваться с персистентным хранилищем надо, иначе можно многое потерять при сбое. Я бы выбрал что-нибудь нереляционное, no-sql-ное, но в этом я не спец вообще. Видится, что для игры SQL неудобен. Думаю, надо читать лучшие практики и писать прототип.
Плюс к 3-му пункту. Монады не являются с необходимостью побочными эффектами. Это механизм абстракции, которым можно обрабатывать и побочные эффекты тоже. Например, монады Maybe и Either не являются «монадами для побочных эффектов». Но они являются структурами поведения со свойством обработки «пустых» данных (Nothing) и обработки данных с возможностью fail-сценария (Left). Монады != побочные эффекты. Побочные эффекты, в основном, сосредоточены в IO.
State, MVar, STVar пожалуй-ка тоже не больно чистоплотны.
State можно считать чистой монадой, так как состояние лишь моделируется. Но это уже философия.
… но покамест мне не известно ни одной книги, аналогичной книге Банды Четырех

Знаю пару книжек:
functional-programming-patterns-in-scala-and-clojure — GOF через скалу/clojure + функциональные паттерны.
clojure-for-domain-specific-languages DSL на кложуре

О, спасибо! Нужно пилить то же самое для Хаскелля.
Спасибо, прочитаю.
НЛО прилетело и опубликовало эту надпись здесь
Done.
Благодарю, судя по содержанию, книга очень достойная. Но в ней, похоже, не затронуты вопросы высокоуровневого дизайна, — только описаны «болты и гайки». Могу ошибаться, конечно.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации