LINUX.ORG.RU

Вопрос терминологии

 , ,


2

3

Скажите, как правильно называется функция, которая возвращает функцию, которая применяет функцию к функциям от агрумента? %))

Вот это:

(define (f/apply ff . fn)
  (lambda args (apply ff (map (lambda (f) (apply f args)) fn))))

Надо написать комментарий, но я не знаю как это обозвать.

Используется, например, так: если нужна функция f(x) = sin(x) * cos(x), пишем (define f (f/apply * sin cos)) и получаем требуемую функцию.

★★★★★

Последнее исправление: Puzan (всего исправлений: 1)
Ответ на: комментарий от system-root

а ещё, мне, не очень понятно что с возвращаемыми типами

А что с ними не так? Возвращается функция, тип аргументов которой совпадает с типами аргументов функций fn, а тип результат совпадает с типом результата ff.

monk ★★★★★
()
Ответ на: комментарий от monk
(define (f/apply ff . fn)
  (lambda args (apply ff (map (lambda (f) (apply f args)) fn))))

Ложь. Знаешь, в чем проблема этой записи? Здесь пользовательские функции и переменные идут вперемешку со служебными. map lambda apply f args fn… Если глаз привык видеть структуру — ок, в противном случае полный атас. Даже в моем варианте с питоньими лямбдами нет такой мешанины. Форматирование, конечно, сильно исправит ситуацию, но в питоне оно принудительное, а в схеме, как видно, этим нормально брезговать.

Звёздочки нужны для записи вариадиков, это да, не зная, можно сильно озадачиться)

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

Две версии

И обе нечитаемое г. А главное, некрасивое.

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

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

Здесь пользовательские функции и переменные идут вперемешку со служебными

Здесь служебное слово только одно - lambda. Да и то, не совсем. А у тебя полный набор, включая звёздочки, жвоеточия и квадратные скобки.

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

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

При чём тут теги? Ты заходишь в тему «Посоветуйте учебник по Хаскель», кидаешь ссылку на книгу по раст. А мог бы просто промолчать. Я не помню от тебя ни одного полезного сообщения в ФП-тредах, зато твой троллинг запоминается. Не обижайся, а делай выводы. Если тебе ОК такое впечатление о себе... Ну что ж.

Кстати, зачем ты подписан на тег «rust»? Чтобы набегать и троллить?

Чтобы ты спросил, блин. А ещё я новость про раст переводил, тоже наверное ради троллинга. Я не твои теги обсуждаю, а твои сообщения.

Ну и что совершенно точно не красит людей, так это переход на личности. Кастовать меня из-за комментария другого человека, до кучи — no way.

Смешно. Ты уже забыл, как сам отметился в этом треде, и как обычно - совсем не конструктивом? Ну так я напомню

И если ты думаешь, что твой пример на Схеме что-то иллюстрирует, то тащемта он выглядит, как непонятное говно.

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

Итого:
1. Ты обиженка с хорошей памятью.

Ну и что совершенно точно не красит людей, так это переход на личности. Кастовать меня из-за комментария другого человека, до кучи — no way.

Смешно. Ты уже забыл, как сам отметился в этом треде, и как обычно - совсем не конструктивом? Ну так я напомню

И если ты думаешь, что твой пример на Схеме что-то иллюстрирует, то тащемта он выглядит, как непонятное говно.

2. Подтасовываешь факты, потому что в первой части комментария «конструктив» (ОМГ) был. Невеликий, разумеется, но ОП большего и не заслуживал, на первый взгляд.

А теперь перестань плодить оффтопик, обиженка.

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

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

Они оба не очень. Но с ценителями красоты lambda я не спорю.

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

Здесь пользовательские функции и переменные идут вперемешку со служебными. map lambda apply f args fn…

map и apply — это нормальные функции. А combinator(*(f(*args) for f in fs)) заставляет считать скобки, чтобы понять, что же дали в cpmbinator. Не говоря уж о args[1:] вместо rest-параметра.

def generate_applicator(*args):
    combinator, fs = args[0], args[1:]
    def applicator(*args):
        return combinator(*(f(*args) for f in fs))
    return applicator

выглядело бы так

(define (generate-applicator combinator . fs)
  (define (applicator . args)
    (apply combinator 
           (for/list ([f fs])
             (apply f args))))
  applicator)

И однозначно видно, что в списке аргументов для какой функции. Даже вариант ТС нормально читается в отличие от «a[0](*(f(*a1)...»

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

Ничего не знаю. Я отлично читаю lambda *a: lambda *a1: a[0](*(f(*a1) for f in a[1:])). Я этот код написал глядя на нормальный вариант, запустил, и он отработал без ошибок. Это типичный код, подсовывающий итератор (в данном случае генераторное выражение) вариадику — читается на ура, если хоть несколько раз напишешь подобное.

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

это да, не зная, можно сильно озадачиться

Я не про озадачиться, а про то, что это как в Си с указателями на функцию. Вот сможешь сходу прочитать и понять что такое int(*f(int(*g)(int x), int z))?

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

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

Я мысленно аплодирую. Теперь мы не просто стараемся оценивать читаемость кода на незнакомом ЯП, а вдобавок еще и не знаем, что это за ЯП). В Питоне указателей нет в принципе. Я не могу принять * за указатель, зная, что код передо мной это код на Питоне.

Вот сможешь сходу прочитать и понять что такое int(*f(int(*g)(int x), int z))?

Сам топи урановые ломы во ртути.

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

Ничего не знаю. Я отлично читаю

Значит просто кто к чему привык. В принципе и перловики строки типа «$??s:;s:s;;$?::s;;=]=>%-{<-|}<&|`{;;y; -/:-@[-`{-};`-{/» -;;s;;$_;" вполне успешно читают.

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

Ничего не знаю. Я отлично читаю

Значит просто кто к чему привык. В принципе и перловики строки типа «$??s:;s:s;;$?::s;;=]=>%-{<-|}<&|`{;;y; -/:-@[-`{-};`-{/» -;;s;;$_;" вполне успешно читают.

Когда напишут — возможно. Через полгода ни один из них успешно не прочитает, не покорпев.

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

цитата_про_овсянку_с_обрезками_ногтей.txt

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

Опять же форматирование автоматическое, нет никаких неоднозначностей.

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

Я не могу принять * за указатель, зная, что код передо мной это код на Питоне.

Да я не про то, что можно перепутать с указателем, а про то, что при чтении a[0](*(f(*a1)... приходится в уме держать

  • a[0](* ... — вызываем функцию в первом элементе массива a с аргументами ...
  • (f — в аргументы попадёт результат функции f...
  • (f(*a1) — от a1 в качестве списка аргументов (тут нормально видно)
  • (f(*a1) for ... — список аргументов для a[0] не от f, а от какой-то длинной конструкции

... и так как список начинается с "(*(", то закрывается также двумя скобками.

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

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

Добавлю лишь, что программист ты в целом хороший, и вещи делаешь полезные (тот же lor notifier). Жаль только, что знакомство с ФП у тебя не задалось. Попробуй видео-курс Москвина на степике. Я серьёзно думаю, что он тебе очень зайдет. Глядишь, через полгода всё это «непонятное говно» вдруг обернется красотой неописуемой, и мы ещё закурим трубку мира. Бывай.

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

Через полгода ни один из них успешно не прочитает, не покорпев.

Если такие конструкции (s;;; ?:, y;;;) пишешь постоянно, а не полгода назад написал, а потом к перлу не подходил, то и через полгода прочитаешь. И даже если не сам писал, всё равно прочитаешь. Я лет 15 назад сам такое и писал и читал и не считал это неудобством.

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

После такого признания я не понимаю, как ты можешь всерьёз выдвигать какие-то претензии: Вопрос терминологии (комментарий). Тем более на питоне так, как я написал, не пишут. Не верю, что кто-то будет возиться с лямбдами.

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

Хорошо, беру свои резкие слова назад и приношу извинения. Правда, с тобой я больше не собираюсь пересекаться, хотя и в игнор не добавляю. Просто информирую. Про

Жаль только, что знакомство с ФП у тебя не задалось.

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

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

После такого признания я не понимаю, как ты можешь всерьёз выдвигать какие-то претензии

Так я признаю, что для того, кто постоянно пишет на питоне, чтение будет без проблем. Но при взгляде со стороны глаз об "(*(f(*" спотыкается. Я бы так писал, если бы меня беспокоила читаемость:

def generate_applicator(combinator, *fs):
    def applicator(*args):
        newargs = f(*args) for f in fs
        return combinator(*newargs)
    return applicator
monk ★★★★★
()
Ответ на: комментарий от Virtuos86

Не верю, что кто-то будет возиться с лямбдами.

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

Я по молодости страдал жавой. Сейчас вспоминаю и осеняю себя крестным знамением. Чур меня, чур!

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

Фабрика аппликаторов XD

Ляпко

Как тесен мир! Я его лично знаю, при первой встрече мне лет 8-9 было, а моя ля маман тогда ему дизайн продукции и торговой марки делала...

timdorohin ★★★★
()
Ответ на: комментарий от Virtuos86
combinator, fs = args[0], args[1:]

Мда. Это не человеческая, это для устращения вероятного противника.

generate_applicator = lambda combinator, *fs: lambda *a1: combinator(*(f(*a1) for f in fs))

В верхней аналогично, но только читаемее нижней она от этого не станет.

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

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

def generate_applicator(combinator, *fs):

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

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

Из-за третьей строчки не скомпилится, и из-за нее же не является идиоматическим кодом

def generate_applicator(combinator, *fs):
    def applicator(*args):
        newargs = [f(*args) for f in fs]
        return combinator(*newargs)
    return applicator
monk ★★★★★
()
Ответ на: комментарий от monk

А на Racket было бы

(define ((generate-applicator combinator . fs) . args)
  (apply combinator 
         (for/list ([f fs]) (apply f args))))

Не помню, можно ли так на классической Scheme

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

Не помню, можно ли так на классической Scheme

Такого каррированного дефайна в схеме нет.

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

Две версии: человеческая и та, которая выглядит примерно как вариант на Схеме.

Где именно так которая человеческая?

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

Тред осиль, уже обсосали всё. Для опоздавших на сеанс повтора не будет.

Virtuos86 ★★★★★
()

Это называется «функция».

Ещё можно использовать модное слово «комбинатор».

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

На безрыбье и этот сгодился бы.

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

Верное замечание. Можно конечно написать одну единственную функцию combinator :: ([b] -> c) -> [[a] -> b] -> [a] -> c, покрывающую сразу все случаи. Но пользоваться ей будет неудобно, в отличие от Python или вот Scheme

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

Можно конечно написать одну единственную функцию combinator

Не покрывается вариант

f/apply ++ drop take :: Int -> [a] -> [a]

В Haskell реально или через Dynamic отрубать типизацию или делать конкретные lift* под каждую комбинацию типов.

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

На тайпклассах не получится?

Может и получится, но у меня фантазии не хватает.

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

Честно говоря, я вот тут думаю что курс Москвина первым рекомендовать не стоит. Сначала я был от него чуть не в восторге. Но сейчас, спустя наверное 2 года, вспоминая как я его проходил - он довольно сложно идёт, довольно много задач на «пошевелить мозгами». Я знаю что это не популярное нынче мнение, но на мой взгляд это (задачи на «пошевилить мозгами») большая проблема потому что оборачивается большими трудозатратами с небольшим результатом. Сам курс на мой взгляд стоило бы продлить по времени в полтора-два раза. При этом исключив (или предварительно объяснив) задачи на «пошевилить мозгами».

Тем не менее курс хороший, особенно если прочитать перед ним хаттона (G. Hutton) в котором некоторые задачи курса разобраны, (например перевод числа в двоичный вид, емнип).

Мне сейчас кажется оптимальный путь такой : ohaskell.guide, hutton/bird (при наличии лучше обе книги, обе хорошие, если нету можно взять тот же learn you a haskell и/или yet another haskell tutorial, емнип), затем курс москвина 1. Курс Москвина в такой компании позволит хорошо закрепить пройденный материал и займёт не так много усилий. Это будет приличная база, кмк.

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

Получается что-то вроде

{-# LANGUAGE GADTs #-}

-- n represents function type, o represents output type
data LApp n o where
  -- no arguments applied (function and output type are the same)
  End :: LApp o o
  -- intentional similarity to ($)
  (:$) :: a -> LApp m o -> LApp (a -> m) o

infixr 5 :$ -- same as :

-- the apply function
listApply :: n -> LApp n o -> o
listApply fun End = fun
listApply fun (p :$ l) = listApply (fun p) l

listMap f End = End
listMap f (p :$ l) = (f p) :$ l

fapply ff fn = \args -> listApply ff $ listMap (\f -> listApply f args) fn

Но listMap типизировать не получается.

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

и ещё вопрос, а

f/apply ++ drop take take :: Int -> [a] -> [a]
должно разворачиваться в
\x y -> drop x y ++ take x y ++ take x y
или должно не проходить проверку типов потому что ++ имеет два аргумента?

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

или должно не проходить проверку типов потому что ++ имеет два аргумента?

Должно не проходить проверку типов.

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

что то мне подсказывает что вот это похоже на то что нужно

https://stackoverflow.com/questions/49628762/lifting-generalization

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

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

Здорово! Надо будет разобраться.

Только для лифта функций нескольких аргументов нужно будет ещё уметь автоматически наворачивать композицию лифтов, так как

magicLift (*) sin cos == liftA2 (*) sin cos

magicLift (*) (+) (-) == (liftA2 . liftA2) (*) (+) (-)
Crocodoom ★★★★★
()
Ответ на: комментарий от AndreyKl

курс на мой взгляд стоило бы продлить по времени в полтора-два раза. При этом исключив (или предварительно объяснив) задачи на «пошевилить мозгами»

Ну не надо! Сейчас редко где найдёшь такой концентрат, который при этом не каша. Особенно это модно в книгах - рассусоливать на 1900+ страниц, как в haskell book.

Чего действительно не хватает - это про large scale design, ghc language extensions (чтоб в одном месте и подробно, с идиоматичными примерами и объяснением принципа работы)... Курс Москвина занял пустую нишу: между введениями и advanced, и не нужно его оттуда двигать, потому что альтернатив ему лично я не знаю.

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

Ну не надо! Сейчас редко где найдёшь такой концентрат, который при этом не каша.

Я согласен что курс вообще говоря как минимум заслуживает внимания. Может быть разбавлять действительно не слишком хорошая идея. Но задачи на «пошевелить мозгами» на мой взгляд это минус. И не хотел бы рекомендовать его первым. В этом смысле я согласен что курс Москвина это «между начальным и продвинутым». Это хорошо сказано.

Что до хаскель бук - говорят многим нравится, я не читал и даже не глядел оглавление. Так что сказать мне нечего.

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

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

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

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

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

AndreyKl ★★★★★
()
Последнее исправление: AndreyKl (всего исправлений: 1)
Ответ на: комментарий от Crocodoom

Кстати, вышла в этом году крайне интересная книга для начинающих «Get Programming with Haskell».

dave ★★★★★
()
Последнее исправление: dave (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.