LINUX.ORG.RU

Функциональщина. Что выбрать?


0

0

Решил в свободное время заняться изучением модного нынче функционального программирования. Встал естественный вопрос: что выбрать? Этих всяких лиспов, хацкелей, оцамлей и т.п. вагон и маленькая тележка. Чтобы не распыляться выбрал Scheme, т.к. его используют в SICP, но настораживает его не слишком большая распространённость и «академичность». С другой стороны, лямбды и прочие «вкусности» потихоньку приходят и во всякие там питоны и даже плюсы. Не холивара окаянного ради, а сугубо для просвещения и развития спрашиваю: что изучать, чтобы не лежало оно потом мёртвым грузом? У каких языков какие плюсы, минусы и области применения?

★★★★

Последнее исправление: Gvidon (всего исправлений: 1)

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

>>Это даст надёжную динамич. типизацию? И какова будет её поддержка со стороны стат. языка? Что значит надёжную статическую? Если функция приравнена undefined, то при форсировании её вызова будет брошено исключение. Его можно отловить в IO. Ну или можно свою кастомную монаду для отлова исключений сваять с нужным поведением.

Бред и неактуальное поскипано.

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

>Бред и неактуальное поскипано.

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

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

>> Скажем так, спецификаций просто нет.

Система типов Хаскеля и есть такая спецификация.

Похоже что тут за спецификацию принимпется информация которая обычно находится в *.h и *.hpp файлах и им подобных.

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

В Haskell такие неоднозначности устранены, потому описания типов можно читать как спецификацию.

Аналогично с ocaml.

SV0L0CH
()
Ответ на: комментарий от archimag

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

Неправильно понимаешь, а скорее всего троллишь.

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

>> скорее всего троллишь.

я никогда не троллю

Мне бабушка рассказывала, что именно так все тролли и говорят...

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

SICP, 3.5. Concepts, Techniques and Models of Computer Programming, 4.5

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

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

Так что с утиной типизацией?

Утиная типизация, ЕМНИМЭ, динамическая по определению.

Вывод типов даёт примерно те же возможности и более.

столь «могучая» типизация, как и ленивые вычисления, по крайней мере у меня создалось такое впечатление после прочтения SICP, была придумана для того, что бы обеспечить применимость функционального подхода с точки зрения производительности.

Производительность - далеко не самая интересная вещь на свете.

Тут же после прочтения топика может создатся впечатление, что главное достоинство Haskell в системе типов...

Да, пожалуй.

Зачем тогда говорить о ФП? а не о языках с «мощной системой статической типизации»?

А есть такие императивные?

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

Но ведь контракты можно проверять и динамически. При этом можно просто делать и более строгие проверки, то же деление на ноль.

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

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

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

Более того, хорошие практики промышленного программирования требуют тщательного ООА перед началом реализации. Хотя бы потому, что эволюция хранилища в РСУБД все равно потребует примерно тех же усилий, что и при статической типизации.

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

Хотя да, если программа не работает с данными в РСУБД и требует скорее поиска правильного алгоритма, чем управления данными, то можно начинать писать как попало, а потом обрабатывать напильником.

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

И да, в условиях плохо определенных задач активно используется прототипирование и RAD, результаты которых после постижения дао выкидываются, и все пишется заново.

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

И тут связка динамический прототип на Лиспе плюс статический продукт на Хаскеле должна рулить, так как нет соблазна выдать наколеночный прототип вместо законченного продукта.

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

Правда, нынче модно из-за лени программистов и жадности заказчика проектировать софт как сарай, а внедрять как небоскреб ©, но это уже отдельная печальная история.

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

Кстати, на первых порах, когда мы пытались прототипировать прямо в коде, изменение модели данных в самом деле выносило 90% кода, что вызывало жуткий когнитивный диссонанс у разработчиков, как описали выше.

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

В конце мне вообще запретили трогать код, а спецификацию-прототип мы вообще разрабатывали в виде UML как результат некой деловой игры с пользователями, где я имитировал компьютер.

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

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

eugine_kosenko ★★★
()

Вот читаю тред: «цацкель», лисп, хаскель, лисп, haskell, схема. Да что же это такое?
Почему все забыли про ML, чем он плох? Объясните мне, пожалуйста, кто-нибудь чем тамошняя система типов плоха (ну по отношению к другим статическим, естественно).
Кстати говоря, никто Qi не смотрел (лисп со статической типизацией, сильно похожей на ML, patter matching'ом и ещё парой вкусностей)?

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

Объясните мне, пожалуйста, кто-нибудь чем тамошняя система типов плоха (ну по отношению к другим статическим, естественно).

Она не плоха, она даже вполне хороша. Там, правда, нет некоторых оччень полезных фишек, которые вполне присутствуют в Хаскеле (хотя не в Haskell98) - тот же forall, например.

никто Qi не смотрел

Там, вроде бы, с выводом типов проблемы.

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

А можно пояснить что такого примечательного в forall (с хаскеллом плохо знаком)? Конкретнее чем он отличается от:

# let f x = x;; (* Надуманно, конечно, но да ладно *)
val f : 'a -> 'a = <fun>

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

> Ну можно взять какой-нибудь нынче популярный F# - таки трендово.

Основные идеи идут из мира лиспа и мира хаскеля. F# - сплошной прагматизм.

dave ★★★★★
()

И всё же мне интересно почему так непопулярен Qi - на мой взгляд попытка взять ML и прикрутить к нему лисповые скобочки должна иметь просто ошеломительный успех (качественная система типов и модулей + возможность лепить лисповые макросы, ну и всякие вкусные «побочные эффекты» в виде pattern matching). Конечно, тут теряется вся «лисповость», но в том же Clojure, вроде бы, неплохо сумели интегрировать абстрактные типы (множества, туплы etc.) в lisp-style.

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

А можно пояснить что такого примечательного в forall (с хаскеллом плохо знаком)?

Собственно, forall используется в двух местах.

1) Экзистеншиалы. Рассмотрим пример, который я приводил для LispDo выше (первый драфт, для простоты). Если у меня есть значение типа LispDo x y, то у меня есть:

а) Некоторое начальное значение типа state

b) Функция перехода, которая по входному значению типа x и текущему состоянию типа state выдаёт либо выходное значение типа y (если вычисление закончено), либо новое значение state (если вычисление не закончено).

Экзистеншиал означает, что я НЕ знаю, какой именно тип сидит внутри state. Я, однако, могу ручаться, что тип начального значения из (а) и тип, использующийся в функции перехода в (б) полностью совпадают. Этот state не торчит наружу. При этом, я могу СОЗДАВАТЬ значения типа LispDo, задавая совершенно произвольный state (какой мне захочется), однако РАБОТАТЬ с ним мне нужно полностью полиморфно. И речь не только обо мне - обалдуй, сидящий рядом, тоже может создавать такие циклы, которые ему хочется, но если он захочет покопаться во внутренностях цикла, то фиг он это сделает без моего разрешения.

2) Полиморфизм более высоких порядков. То есть, forall a. a -> a - это действительно то же самое, что a -> a. А вот, скажем:

f :: (forall a. a -> a) -> Integer
f h = h 1 + length (h "Hello")
Пример выморочный, конечно.

Более полезным примером является монада ST. Любое вычисление внутри ST сопровождается неким типом-маркером, то есть, если мы вычисляем, например, целое число, то тип результата будет ST a Integer. Кроме того, внутри монады заводятся некие «указатели», опять-таки с маркером: STRef a x. После чего вычисление из императивного (с указателями) преобразуется в чистое функцией runST, имеющей тип

runST :: (forall a. ST a x) -> x
Использование forall гарантирует, что тип a не будет участвовать в x. Скажем, невозможно сделать runST s, если s имеет тип ST a (a -> a). Что более важно, невозможно сделать runST s, если s имеет тип ST a (STRef a Integer). Поэтому «указатели», заведённые внутри ST, никак не могут выскочить наружу, благодаря чему значение, получаемое в результате, будет уже чистым.

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

>Почему все забыли про ML, чем он плох? Объясните мне, пожалуйста, кто-нибудь чем тамошняя система типов плоха

Я вот недавно решил ради саморазвития выучить ocaml. И что характерно, никакой особой разници с Haskell не заметил.

Смутило только отсутствие классов типов и других средств перегрузки. Только всвязи с этим отдаю предпочтение Haskell.

PS

В F# не вникал, может там и есть чтото ценное.

SV0L0CH
()
Ответ на: комментарий от Miguel

не троллинга ради, а токмо ради самообразования, можно пример вызова функции f с конкретной функцией h? Интересует, как h примет и 1, и «Hello»

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

Я вот недавно решил ради саморазвития выучить ocaml. И что характерно, никакой особой разници с Haskell не заметил.

OCaml нечист. Вследствие этого у него, например, f и fun x -> f x - разные вещи (даже если f имеет нужный тип).

OCaml имеет систему модулей и функторов, до некоторой степени заменяющую хаскелевские классы. Очень, кстати, занятная система сама по себе.

OCaml умеет subtyping (в форме наследования), что может быть и достоинством и недостатком.

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

можно пример вызова функции f с конкретной функцией h?

f id

Более подробно:

MigMit:~ MigMit$ ghci
GHCi, version 6.10.4: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer ... linking ... done.
Loading package base ... linking ... done.
Prelude> :set -XRankNTypes
Prelude> let {f :: (forall a. a -> a) -> Int; f h = h 1 + length (h "Hello")}
Prelude> f id
6

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

Ой, да, понятно :) Это всё последствия НГ :)

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

Да, справедливости ради, всё таки хочу уточнить: тут я говорил ML, подразумевал OCaml (т.к., скажем, в SML всё же некоторые _базовые_ фичи реализованы не так).

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

>>И всё же мне интересно почему так непопулярен Qi

что есть Qi ?

По тому что нашёл в википедии могу предположить что Qi сочетает в себе основные черты C++ и perl, много всего напихано в одну кучу и всё можно сделать огромным количеством способов и через месяц самому будет непонятно что насочинял. Кроме этого оно лиспоподобно...

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

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

> По тому что нашёл в википедии

Википедию лучше не читать, там написано очень много бреда.

Qi сочетает в себе основные черты C++ и perl, много всего напихано в одну кучу

Нет, в qi очень прилично все продумано и реализовано. Отдельного внимания заслуживает система типов. Про язык лучше почитать тут [1]

Кроме этого оно лиспоподобно...

Да, это очень большой минус.

[1] http://www.lambdassociates.org/Book/contents.htm

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

>А кроме этого ужаса - pdf разбитого на картинки ничего нет? Ато глаза болеть начинают :(

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

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

> автор qi забил на него, поскольку статическая типизация оказалась никому не нужна.

Потому что автор оказался несколько неадекватным, и обиделся, что его qi не стал шибко популярным. И кстати, он его не забросил, а решил перенести на более модную и мейнстримную платформу (python или clojure).

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

>И кстати, он его не забросил, а решил перенести на более модную и мейнстримную платформу (python или clojure).

забросил, и уехал медитировать в Индию.

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

Если за двадцать лет так почти никому и не понадобилась статическая типизация в липе, то какой отсюда вывод напрашивается? что статическая типизация может быть полезна в очень узких областях, где нужно проверять только корректность( хотя это обычно какой-нибудь ещё и реалтайм)?

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

>> автор qi забил на него, поскольку статическая типизация оказалась никому не нужна.

Толсто.

Зато теперь можно развить тему и поговорить о проблемах возникающих при той или иной типизации.

Както взялся за задачу конвертации XML в структуры данных описаные на Haskell или OCaml. Исходными данными должны быть схемы XSD. После нескольких неудачных попыток я это занятие оставил, но осталось несколько вопросов.

Как охарактеризовать типизацию принятую в XSD? Есть ли какие аналоги для атрибутов, которые в свою очередь так же имеют тип?

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

и ещё в qi типизация была богаче хаскелльной, но все равно оказалась ненужна.

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

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

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

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

Если за двадцать лет так почти никому и не понадобилась статическая типизация в липе

Если за двадцать лет так почти никому и не понадобились макросы в Хаскеле...

Если за двадцать лет так почти никому и не понадобились замыкания в C...

Если за двадцать лет так никому...

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