LINUX.ORG.RU

[FP] Помогите с выбором языка для ФП


0

4

Здравствуйте, пожалуйста порекомендуйте какой язык выбрать из списка и по возможности книгу/туториал по нему, скажите какие у него перед остальными плюсы: - Erlang - Scala - Clojure - Scheme - OCaml Или что-то другое. Python не предлагать, как впрочем и Haskell. Если язык не из списка - то интересует именно инопланетный синтаксис и возможность писать на чистом ФП. Желательно, чтобы язык был не чисто академическим, имелась возможность работы с тулкитами (Qt, GTK, Tk).

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

p.s.: А Refal еще жив? Может он шевелится и имеет связки с тулкитами и прочим?


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

> Ну да конечно... всего то нужно переписать код до состояния не использования системного стека, научить прыгать между потоками, научить взаимодействию с AsyncIO платформы, научить отменять группу вычислений одним вызовом метода,...

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

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

> Ты хоть раз видел ассемблерный код генерируемый компилятором С?

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

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

Полный код покажи, пожалуйста. А то непонятно ничего.

newtype RealWorld = RealWorld (BigInt)
newWorld = RealWorld(BigIntZero)
updateWorld RealWorld(i) = RealWorld(increment i)

Чего тут не ясно?

Покажи реализацию функции

fork :: IO () -> IO ()

Сразу после того как ты покажешь полную реализацию свой. Без завязки на готовую монаду IO.

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

Но как она будет работать я уже писал. Просто делаем unsafePreformIO в другом потоке и все.

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

>Я и говорю - одна из самых простых монад, реализуется тривиально, в отличии от той же ИО

Я тут реализацию IO в десяток строк уже приводил. Мигель даже согласился что это таки полноценное IO.

Для сравнения реализация Async вылилась в 26 килобайт кода.

Я уж не говорю про то, что Async - это просто элементарная обертка вокруг той же ИО.

Я вроде как говорил что я это не для хаскеля делал.

Кстати слабо ответить за базар и показать монаду Async на хаскеле? Только давай по честному. Используй асинхронный ввовд/вывод.

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

>Конечно, нет. Во внутренний блок можно попасть откуда угодно и выйти куда угодно.

А жжесть!!!!!!!

Это код не на С. Я вообще не знаю ни одного языка даже близко похожего на то что ты тут описал.

Особенно весело наблюдать несогласованность внутри твоего же кода.

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

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

> Я тут реализацию IO в десяток строк уже приводил. Мигель даже согласился что это таки полноценное IO.

Так это реализация ИО на базе самой ИО (то есть когда ИО уже есть). Ты пойми, в самом языке никакой реализации ИО нет - это просто некоторая монада, о которой известно только ее название. А вот реализация ИО в рантайме - это бОльшая часть компилятора хаскеля, в частности - вся кодогенерация, все оптимизации и т.д. Осилишь в 10 строк?

Я вроде как говорил что я это не для хаскеля делал.

А ИО есть в любом языке, не только в хаскеле. Просто в хаскеле можно писать чистый код (который не находится внутри ИО), а в других языках - нельзя. Он внутри ИО по дефолту. Другими словами и реализовывать ничего не надо.

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

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

А давай ка ты ответишь за базар и напишешь этот код.

Только убедись что его компилятор С компилирует и стек выбивает.

А то у меня складывается впечатление что ты С в глаза не видел.

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

> Это код не на С.

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

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

нехвостовой факториал, я тебе уже говорил.

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

>во-первых, при чем тут си?

При том, что речь шла про С.

во-вторых - любой вызов ф-и из другой ф-и и будет примером такого внутреннего блока.

Что такое «внутренний блок»? Что это за терминология? Первый раз слышу.

Давай как ты покажешь мне код на С с этим самым внутренним блоком.

нехвостовой факториал, я тебе уже говорил.

Я вроде как уже не раз говорил, что речь идет о коде внутри функции. Все вызовы функций остаются как есть. Так что мимо.

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

> >Конечно, нет. Во внутренний блок можно попасть откуда угодно и выйти куда угодно.

А жжесть!!!!!!!

Это код не на С.

setjmp/longjmp

ky-san
()
Ответ на: комментарий от winduzyatnik

Только убедись что его компилятор С компилирует и стек выбивает.

int f(){
	f();
	return 0;
}

void main(){
	f();
}
anonymous
()
Ответ на: комментарий от winduzyatnik

> При том, что речь шла про С.

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

Что такое «внутренний блок»? Что это за терминология? Первый раз слышу.

«Внутренний блок» = «блок который внутри». Тут не нужна никакая терминология.

Я вроде как уже не раз говорил, что речь идет о коде внутри функции.

Ну так внутри ф-й есть другие вызовы ф-й. Ты об этом не знал?

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

> Ты меня с Мигелем не путеашь?

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

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

>Речь шла не про си, а о том, что ты якобы из любого кода сделаешь эквивалентный код с хвостовыми вызовами, просто расставив метки.

Речь шла про код _внутри функции_.

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

А где я спорил с тем что вызовом функции можно стек переполнить?

Ты без вызова функции попробуй это сделать.

Размещать мегамассивы в стеке не считается.

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

> Речь шла про код _внутри функции_.

Ну вот у меня внутри ф-и по очереди вызываются f1(), f2(); сделай вызов f1() хвостовым мне.

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

> Ты без вызова функции попробуй это сделать.

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

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

Ничего, кроме передачи управления между разными блоками

ky-san
()
Ответ на: комментарий от winduzyatnik

Давай немного по-другому. [code] void g(){...}; void h(){...};

void f(){    f();    h(); }

void main(){    f();    h(); } [/code] что делают ф-и g() и h() не важно (предполагается что только там никаких функциональных вызовов и т.п. нет). давай преобразуй это в гото с метками и потом в хвосторекурсивную форму.

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

Давай немного по-другому.

void g(){...};
void h(){...};

void f(){
	f();
	h();
}

void main(){
	f();
	h();
}

что делают ф-и g() и h() не важно (предполагается что только там никаких функциональных вызовов и т.п. нет). давай преобразуй это в гото с метками и потом в хвосторекурсивную форму.

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

[code] void main(){ f(); g(); } [/code] вот так

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

Тут:

В рантайме? Да какая разница, что там-то будет?

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

Сразу после того как ты покажешь полную реализацию свой. Без завязки на готовую монаду IO.

Я показал. Готовая IO возникает только в рантайме, рантайм - весь - забит в компилятор и программеру не виден.

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

> Готовая IO возникает только в рантайме

Тут уже несколько страниц до него этот факт донести пытаются. Бесполезно.

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

Ты приписываешь мне, то чего я не говорил и упорно это опровергаешь. Ты что думаешь, я на это поведусь?

Разговор шёл об управляющих конструкциях языка С ни о чем более.

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

>> Мигель даже согласился что это таки полноценное IO.

Врёшь.

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

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

Но что характерно так их и не продемонстрировал.

Даже если ты сумеешь впоследствии доказать, что я не прав - это не даёт тебе права утверждать, что я УЖЕ СЕЙЧАС согласился. Это называется «ложь».

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

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

Но ты же тоже не приводишь реализацию свой монады.

Все что ты показал это тупое делегирование готовой реализации.

Все что нужно в моем случае это просто создать поток и передать ему значение типа IO (). Далее тупо сделать unsafePerformIO и радоваться.

Сделать это можно только закопавшись в потроха рантайма. Или ты мне тут компилятор хаскеля предлагаешь написать?

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

Но ты же тоже не приводишь реализацию свой монады.

Читай выше: data MIO x =...

Это и есть реализация МОНАДЫ.

Реализация РАНТАЙМА - да, делегирование, но в том и прелесть, что РАНТАЙМ спрятан в компилятор и может быть сделан как угодно. Во всяком случае, его МОЖНО сделать, иначе у меня ничего не работало бы.

Все что нужно в моем случае это просто создать поток и передать ему значение типа IO ().

Так напиши, если просто.

Сделать это можно только закопавшись в потроха рантайма.

Ну, вот у меня реализация fork написана отдельно от рантайма.

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

> Разговор шёл об управляющих конструкциях языка С ни о чем более.

Ну так я выше привел пример кода на С. Перепиши с хвостовой рекурсией.

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

Ну, ты и зануда. Пришлось читать про ffi.

[code] foreign import ccall «wrapper» wrap :: (Ptr () -> ()) -> IO (FunPtr (Ptr () -> ()))

foreign import ccall «process.h _beginthread» _beginthread :: FunPtr (Ptr () -> ()) -> Int -> Ptr () -> IO WordPtr

fork :: IO () -> IO () fork arg = do fn <- wrap (\_ -> unsafePreformIO arg) _ <- _beginthread fn 0 nullPtr freeHaskellFunPtr fn [/code]

[quote] Ну, вот у меня реализация fork написана отдельно от рантайма. [/quote] Жулик ты.

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

Ай, как не хорошо.

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

>Ну так я выше привел пример кода на С. Перепиши с хвостовой рекурсией.

Мальчик ты здоров?

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

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

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

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

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

[code] void f() {...}; void g() {...}; void h() {...};

void fun1(){f(), g();} void fun2(){f(), h();}

void main(){fun1(), fun2();} [/code] и здесь опять f() нехвостовые. Стек в _данном примере_ конечно не упадет - но расти будет, в результате можно сделать миллион подобных вложенных ф-й и он-таки упадет. Ах, да, еще ты можешь сказать - раз нет рекурсии, то мы все ф-и заинлайним. Но это уже вообще софизм.

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

foreign import ccall «wrapper»

Потрясающе. Может, ещё объяснишь, какое это имеет отношение к ТВОЕЙ РЕАЛИЗАЦИИ IO?

Жулик ты.

Отнюдь. Я просто хочу разделять монаду и рантайм.

Miguel ★★★★★
()
Ответ на: комментарий от anonymous
 
void f() {...}; 
void g() {...}; 
void h() {...};

void fun1(){f(), g();} 
void fun2(){f(), h();}

void main(){fun1(), fun2();} 
anonymous
()
Ответ на: комментарий от Miguel

>Потрясающе. Может, ещё объяснишь, какое это имеет отношение к ТВОЕЙ РЕАЛИЗАЦИИ IO?

Ну то есть тебе можно заявлять что за тебя все сделает «рантайм», а мне компиляторную магию использовать нельзя. Я тебя правильно понял?

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

>Сперва ты сказал, что можно любой сишный код,

Мальчик ты точно больной.

Я всегда говорил только про код внутри одной функции. Про несколько функций я ничего не говорил.

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

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

Почему нельзя? Можно, конечно. Я хочу лишь двух вещей: 1) твоя реализация монады IO не должна содержать ссылок на уже имеющуюся монаду IO (замечание: реализация именно МОНАДЫ; я переживу, если в реализации функций read/write/etc. IO будет как-то использоваться), и 2) увидеть функцию fork для ТВОЕЙ реализации IO (а не для встроенной IO). Ну, ещё хочу, 3) чтобы оно не святым духом работало, а чтобы для этого можно было написать рантайм (и убрать его в компилятор).

Всё это я тебе предоставил (причём без встроенной IO даже в реализации функций read/write/fork). Теперь я хочу того же самого от тебя, от твоей реализации. Вот тогда, если это будет достаточно несложно, я соглашусь, что многопоточность в твоей реализации тоже возможна.

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

> Я всегда говорил только про код внутри одной функции.

Ну так в чем тогда проблема с рекурсией? Там же код только одной ф-и.

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