LINUX.ORG.RU

Ответ на: комментарий от Deleted

И часто это используется?

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

Я правильно понимаю, что это ломает саму идеологию?

Не больше, чем unsafe в Rust.

monk ★★★★★
()
Ответ на: комментарий от anonymous

Просто раздражает такая нечестность

по мне так всё честно и улучшать не особо есть куда. максимум — допилить до состояния cargo install, и то не обязательно

Бросьте камень в того, кто скажет, что IDE для Haskell - не больная тема.

я intellij-haskell пользуюсь. для проекта, ведомого одним разработчиком работает восхитительно. не без недоделок, конечно, но не фатально.

littlechris ★★★
()
Ответ на: комментарий от Deleted

qsort со случайным выбором pivot, например.

Функция получается чистая, но внутри использует случайное число, которое меняется от запуска к запуску. Без хаков такое невозможно записать в системе типов х-ля.

Crocodoom ★★★★★
()
Ответ на: комментарий от aedeph_

Санки и fsharp'овый lazy подойдут?

Ещё раз: на любом языке можно писать как на хаскеле. Даже на си. Просто у разных языков синтаксис позволяет в каком-то стиле писать легче, а в каком-то сложнее. В F# отделять всю чистую логику от нечистой и использовать всюду lazy менее удобно, чем использовать аналогичную семантику в хаскеле. Зато в хаскеле неудобно писать функции, которые в одном алгоритме совмещают ввод-вывод и сложную логику и требуют не ленивых вычислений.

Помимо хаскела чистыми ленивыми MLами были: Miranda, LazyML, Orwell, Clean, ...

monk ★★★★★
()
Ответ на: комментарий от Crocodoom

Тогда такой функции показано использовать NOINLINE. Может быть, функция и будет чистой, а вот будет ли ссылочно-прозрачной? Это важнее, чем чистота

dave ★★★★★
()
Ответ на: комментарий от monk

Ещё раз:

Еще раз: херня, повторенная многократно, херней быть не перестает.

на любом языке можно писать как на хаскеле. Даже на си.

Интересно было бы посмотреть на карринг или паттерн-матчинг на Си.

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Интересно было бы посмотреть на карринг или паттерн-матчинг на Си.

карринг

// f x y z = x + y + z

int _f2(int z, list x_y)
{
  return z + (int)list_ref(x_y, 0) + (int)list_ref(x_y, 1);
}

GClosure* _f1(int y, int x)
{
  return g_cclosure_new(G_CALLBACK(_f2), make_list2(x, y), destroy_list)
}

GClosure* f(int x)
{
  return g_cclosure_new(G_CALLBACK(_f1), (gpointer)x, NULL)
}

паттерн-матчинг

/*
  take  0     _           =  []
  take  _     []          =  []
  take  n     (x:xs)      =  x : take (n-1) xs
*/
list* take(int n, pair* l)
{
  void *x;
  pair *xs;
  cmatch2* match2 = make_match2_int_ptr(n, l);
  if(invoke(match2, match_exact_num(0), NULL) return pair(NULL, NULL);
  elseif(invoke(match2, NULL, match_list(NULL, NULL)) return pair(NULL, NULL);
  elseif(invoke(match2, match_num(&n), match_list(&x, &xs)) return pair(x, take(n-1, xs));
}

monk ★★★★★
()
Ответ на: комментарий от eao197

Это называется «программировать как на Хаскеле»?

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

Хотя на Си такое используется достаточно редко, а вот в C++ или Common Lisp — сплошь и рядом.

monk ★★★★★
()
Ответ на: комментарий от monk

Именно так.

Боюсь, это только у кого-то в голове так.

Когда сначала формулируешь задачу в терминах хаскеля, а потом точно переносишь семантику в Си или что-то ещё.

Ничего вы не перенесли. Вы руками на C написали то, что автоматически делает транслятор Хаскеля (да и то он это делает, наверняка лучше и компактнее).

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

Я подозревал, что у вас собственное понимание сего афоризма. Так оно и получилось. Посему вы и перевернули все с ног на голову.

eao197 ★★★★★
()

нельзя, эта тайна за семью печатями.

qnikst ★★★★★
()
Ответ на: комментарий от eao197

Вы руками на C написали то, что автоматически делает транслятор Хаскеля

Правильно. Если задача стоит как «сделать функцию от одного аргумента, которая возвращает замыкание», то по-другому задачу не решить.

Также как если стоит задача «написать GUI используя классы с наследованием», то на Си будет GObject или что-то подобное.

(да и то он это делает, наверняка лучше и компактнее

Разумеется, также как классы и объекты Си++ лучше и компактнее GObject. Но на Си за счёт ручного выполнения можно явно расширить то, что в Си++ или хаскеле намертво зашито в трансляторе. Например, GObject умеет создавать новые классы во время работы программы.

Также и карринг с паттерн-матчингом вручную позволяет, например, динамически изменять правила матчинга, указывать явно время жизни объектов (а не надеяться на сборщик мусора). Явно управлять кэшированием результатов и т.д.

Я подозревал, что у вас собственное понимание сего афоризма.

А какое у вас?

monk ★★★★★
()
Ответ на: комментарий от monk

А какое у вас?

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

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

Поэтому писать на Хаскеле как на Фортране еще можно попробовать, но вот на Фортране или на Си как на Хаскеле — нет. Что ваши примеры ярко и продемонстрировали.

eao197 ★★★★★
()
Ответ на: комментарий от anonymous

We use Haskell in production to retrieve thousands of tweets per seconds in real time. Before we used PHP and it couldn't handle more than about 15 tweets per seconds. Haskell was really the best tool for the job.

😂🤣

anonymous
()
Ответ на: комментарий от Crocodoom

Годный пример, спасибо.

qsort со случайным выбором pivot, например.

Deleted
()
Ответ на: комментарий от qnikst

qsort - inplace если что, он так и так содержит эффекты, и не является чистой функцией.

Если эффекты не используют IO, то является чистой:

import qualified Data.Vector.Generic as V 
import qualified Data.Vector.Generic.Mutable as M 

qsort :: (V.Vector v a, Ord a) => v a -> v a
qsort = V.modify go where
    go xs | M.length xs < 2 = return ()
          | otherwise = do
            p <- M.read xs (M.length xs `div` 2)
            j <- M.unstablePartition (< p) xs
            let (l, pr) = M.splitAt j xs 
            k <- M.unstablePartition (== p) pr
            go l; go $ M.drop k pr
monk ★★★★★
()
Ответ на: комментарий от eao197

Поэтому писать на Хаскеле как на Фортране еще можно попробовать

То есть

  while cond body = do
    condVal <- cond
    when condVal $ do
      body
      while cond body

  for init cond step body = do
    init
    while cond $ do
      body
      step

  main = do
    n <- readLn
    x <- newIORef 1
    for
      (return ())
      (do
        xVal <- readIORef x
        return $ xVal < n)
      (do
        xVal <- readIORef x
        writeIORef x $ xVal + 1)
      (do
        xVal <- readIORef x
        putStrLn $ show xVal)

выглядит лучше, чем мой пример на Си?

monk ★★★★★
()
Ответ на: комментарий от monk

Вы всерьез собираетесь доказывать, что вот это:

  take  0     _           =  []
  take  _     []          =  []
  take  n     (x:xs)      =  x : take (n-1) xs
и вот это:
list* take(int n, pair* l)
{
  void *x;
  pair *xs;
  cmatch2* match2 = make_match2_int_ptr(n, l);
  if(invoke(match2, match_exact_num(0), NULL) return pair(NULL, NULL);
  elseif(invoke(match2, NULL, match_list(NULL, NULL)) return pair(NULL, NULL);
  elseif(invoke(match2, match_num(&n), match_list(&x, &xs)) return pair(x, take(n-1, xs));
}
есть код, который написан в одном стиле?

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

Что до вашего почти императивного кода на Хаскелле, то я не понял, что он должен проиллюстрировать.

eao197 ★★★★★
()
Ответ на: комментарий от monk

только `go` с эффектами, `V.modify` радостно делает runST, (IO это `ST RealWorld#`), т.е. утверждать, что это чистая функция я бы стал с оговорками.

qnikst ★★★★★
()
Ответ на: комментарий от eao197

есть код, который написан в одном стиле?

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

match(_eqnum(0), _any)              return emptylist; 
_match(_any, _emptylist)            return emptylist;
_match(_num(&n), _list(&x, &xs))    return pair(x, take(n-1, xs))

Что до вашего почти императивного кода на Хаскелле, то я не понял, что он должен проиллюстрировать.

То же, что код с замыканиями на Си. Почти на любом языке можно писать почти в любом стиле. Вопрос только в удобстве.

monk ★★★★★
()
Ответ на: комментарий от qnikst

только `go` с эффектами

да, но несмотря на это qsort чистая

monk ★★★★★
()
Ответ на: комментарий от monk

Да в одном.

Понятно, вопросов больше не имею.

Почти на любом языке можно писать почти в любом стиле. Вопрос только в удобстве.

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

eao197 ★★★★★
()
Ответ на: комментарий от monk

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

Мне кажется, ты хотел сказать не «на любом языке можно писать как на Хаскелле», а «если ты способен в голове транслировать код с Хаскелла в любой язык, то ты можешь на любом языке писать как на Хаскелле».

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

«на любом языке можно писать как на Хаскелле»

К сожалению, это невозможно. Так бывает крайне сложно писать на F# или Scala, а вы про какой-то там Си++... Ах, даже про Си

dave ★★★★★
()
Последнее исправление: dave (всего исправлений: 2)
Ответ на: комментарий от tailgunner

«на любом языке можно писать как на Хаскелле», а «если ты способен в голове транслировать код с Хаскелла в любой язык, то ты можешь на любом языке писать как на Хаскелле»

Зачем в голове? Можно на листочке, в макросах или даже ad-hoc кодогенератор написать. И из второго утверждения следует первое.

Кстати, в тему: https://habrahabr.ru/post/31541/

Я заметил, что мыслю на Python и иногда даже на Haskell в какой-то мере — несмотря на то, что я использовал Haskell совсем немного. Я постоянно обнаруживаю в себе желание использовать идиомы из этих языков и подсчитываю, насколько сильно я мог бы сократить код, если бы использовал эти языки (которые, хоть и сильно отличаются друг от друга, оба намного мощнее того языка, который я использую на работе — C#).

И приводит попытки думать на Haskell и писать на C#:

string.Join("\n", mylist.ConvertAll<string>(
    delegate(Foo foo)
    {
        return foo.Description();
    }).FindAll(
    delegate(string x)
    {
        return x != "";
    }).ToArray());

monk ★★★★★
()
Ответ на: комментарий от monk

Что здесь от попыток «думать на Хаскелл»? Такие вещи делались в лет на чисто ООП-шном Ruby еще 15 лет назад.

mylist = [1, 3.0, "a", "", "b", 42]

puts mylist.map {|x| x.to_s}.select {|x| !x.empty?}.join("\n")
А за 20 лет до этого на еще более чисто ООП-шном SmallTalk-е.

eao197 ★★★★★
()
Ответ на: комментарий от monk

И приводит попытки думать на Haskell и писать на C#

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

anonymous
()
Ответ на: комментарий от monk

«на любом языке можно писать как на Хаскелле», а «если ты способен в голове транслировать код с Хаскелла в любой язык, то ты можешь на любом языке писать как на Хаскелле»

Зачем в голове? Можно на листочке

Очень уж много листочков понадобится.

в макросах

Нет. Типы проверять всё равно придется в голове.

или даже ad-hoc кодогенератор написать

Это уже не будет «любой язык».

попытки думать на Haskell и писать на C#:

Сразу вспоминается Эллочка-людоедка и мексиканский тушкан.

tailgunner ★★★★★
()
Ответ на: комментарий от monk

Вообще, если есть склонность «думать на хаскель», может лучше заняться математикой? С какого то бодуна решили, что программирование и математика близкие дисциплины. Хотя там световые годы меж ними как по мне.

anonymous
()
Ответ на: комментарий от tailgunner

Очень уж много листочков понадобится.

Да нет. Большая часть вполне реализуема функциями: формирования замыкания, ленивый вызов замыкания, проверка типа значения...

Примерно как GObject вместо Java.

Типы проверять всё равно придется в голове.

Можно проверять в рантайме. Всё равно что-то типа GValue придётся делать. Можно на листочке (или в файле) как доказательство теоремы.

monk ★★★★★
()
Ответ на: комментарий от monk

Кстати, в тему: https://habrahabr.ru/post/31541/

Согласен. После лиспо-хаскелей все кажется дерьмом, весь костыльный «мейнстрим» :(

Так почему же не начать бизнес сразу инвестируя в эти «лучшие технологии», ведь найти лисперов и хаскелистов в 2018 году не так уж проблематично.

mimimimi
() автор топика
Ответ на: комментарий от mimimimi

Так почему же не начать бизнес сразу инвестируя в эти «лучшие технологии»

Ну, например? Какой бизнес будет проще начать используя разработку на Haskell, а не на какой-нибудь Java/Scala/Kotlin/Ceylon или C#/F#? Или даже на Go?

eao197 ★★★★★
()
Ответ на: комментарий от eao197

Какой бизнес будет проще начать используя разработку на Haskell

Где нужна корректность, меньшие сроки разработки, быстрое прототипирование, меньше багов на многоядерных системах?

mimimimi
() автор топика
Ответ на: комментарий от mimimimi

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

Хотя бы в общих чертах.

eao197 ★★★★★
()
Ответ на: комментарий от mimimimi

Где нужна корректность, меньшие сроки разработки, быстрое прототипирование

Согласен только по первому пункту.

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

Быстрое прототипирование: тоже без системы типов работать не будет, а типы быстро не сделать. Будет сильно проигрывать, например, питону

monk ★★★★★
()
Ответ на: комментарий от eao197

Вот так сразу подробно не скажу, ибо нет у меня (думаю) нюха торгаша.

Но того, что я написал разве не достаточно для _любой_ сферы? Много плюсов же.

mimimimi
() автор топика
Ответ на: комментарий от mimimimi

Про меньшее число разработчиков забыл.

С этим пунктом тоже согласен. Но для бизнеса преимущество спорное: каждый из этого меньшего числа требует больше денег, чем разработчик на Java. Если вдруг кто-то заболел, то это сильнее сказывается на проекте.

monk ★★★★★
()
Ответ на: комментарий от monk

Haskell хуже делится на модули, так как типы необходимо согласовывать по всей программе

на жабе тоже также, надо думать перед написанием кода.

Также разработчиков на Java проще найти

этом наверное и ответ

mimimimi
() автор топика
Ответ на: комментарий от mimimimi

Где нужна корректность

К слову, если разработчики изначально не озаботились ей, то исправить не легче, чем в C++

https://github.com/leksah/leksah/issues/455

(leksah:19935): Gtk-CRITICAL **: gtk_text_view_scroll_mark_onscreen: assertion 'get_buffer (text_view) == gtk_text_mark_get_buffer (mark)' failed

висит ошибка уже полгода. Я сунулся в исходники и понял, что не могу даже найти функцию, из которой вызывается этот кусок.

monk ★★★★★
()
Ответ на: комментарий от mimimimi

Но того, что я написал разве не достаточно для _любой_ сферы?

Нет, конечно. Например, сфера поддержки древнего корпоративного легаси, она же попадает в понятие _любой_ сферы. А выгод от Haskell-я с Lisp-ами нам нет от слова совсем.

Много плюсов же.

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

Любые маргинальные технологии оказываются невыгодными для массового потребления. И применяются либо в тех узких нишах, где эти технологии имеют существенные преимущества (какое-нибудь специализированное компиляторостроение или DSL-е строение для наукоемких областей), либо на вспомогательных ролях в уже успешных организациях (как, например, разработка Bond-а в Microsoft или Queryparser у Uber, хотя хз что там у Uber-а с успешностью).

eao197 ★★★★★
()
Ответ на: комментарий от monk

Большая часть вполне реализуема функциями: формирования замыкания, ленивый вызов замыкания, проверка типа значения...

Типы проверять всё равно придется в голове.

Можно проверять в рантайме.

А. То есть писать на диалекте Хаскелла, проверяющем типы в рантайме. Тебе часто говорят, что ты поехавший?

tailgunner ★★★★★
()
Ответ на: комментарий от monk

Прям история успеха. «Мы были молоды, писали на Haskell, как могли…»

Virtuos86 ★★★★★
()
Ответ на: комментарий от mimimimi

на жабе тоже также, надо думать перед написанием кода.

Не надо. Например, пишешь ты кусок кода, который должен что-то вывести пользователю. Можешь не думая создать заглушку gui.show(result). Если в другом месте потребуется указать дополнительный параметр, тот пользователь сможет написать gui.show(result, params). Если в третьем месте результат будет иметь другой тип, тоже не проблема. А в Haskell приходится заранее придумать какие именно типы должен принимать gui.show. Или какие классы типов. Если классы, то какие методы должны быть у этих классов.

monk ★★★★★
()
Ответ на: комментарий от tailgunner

То есть писать на диалекте Хаскелла, проверяющем типы в рантайме. Тебе часто говорят, что ты поехавший?

Нет. Писать на Си, используя функции с семантикой хаскелла. GObject тоже наследование классов в рантайме проверяет.

monk ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.