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

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

Публикации

Истории