| [Haskell] point-free - этюды | |
| От: | nikov | ||
| Дата: | 15.10.09 12:31 |
| Здравствуйте, lomeo, Вы писали: L>>>
МС>>Да, спасибо, это оно самое. МС>>Попытался расписать типизацию на бумажке — чуть мозг не свернул L>На самом деле ничего страшного здесь нет. Просто никогда так не пиши А по-моему всё предельно понятно. Почему бы так не написать? Мне тоже сразу придумался именно этот код. 22.10.09 20:52: Ветка выделена из темы [Haskell] where в let ... in Автор: Мишень-сан — КодтДата: 15.10.09 |
| Re: [Haskell] point-free - этюды | |
| От: | Мишень-сан | ||
| Дата: | 15.10.09 12:54 |
| Здравствуйте, nikov, Вы писали: N>А по-моему всё предельно понятно. Почему бы так не написать? Мне тоже сразу придумался именно этот код. Ну для меня этот код пока что слабочитабелен. Haskell я начал изучать несколько дней назад. Но запомню |
| Re[2]: [Haskell] point-free - этюды | |
| От: | nikov | ||
| Дата: | 15.10.09 13:24 |
| Здравствуйте, Мишень-сан, Вы писали: МС>Ну для меня этот код пока что слабочитабелен. Haskell я начал изучать несколько дней назад. Ну тогда еще тренировочные задачки 1) Написать функцию clone, которая повторяет каждый символ в строке (или в списке) заданное число раз. Например clone 2 "abc" должно дать "aabbcc". 2) Написать функцию power, которая повторяет строку (или список) заданное число раз. Например power 2 "abc" должно дать "abcabc". 3) Написать функцию fpower :: Int -> (a -> a) -> (a -> a), которая возводит функцию в указанную степень. Например fpower 3 (*2) должно вернуть функцию эквивалентную троекратному применению (*2), то есть (*2).(*2).(*2) или (*8). 4) Написать функцию rotateLeft, которая производит циклическую перестановку элементов списка влево на указанное число позиций. Будет ли твой код работать, если список бесконечный? А если указанное число позиций больше, чем длина списка? Попробуй написать в point-free style c использованием существующих комбинаторов. |
| Re[3]: [Haskell] point-free - этюды | |
| От: | Пельмешко | ||
| Дата: | 16.10.09 07:02 |
| Здравствуйте, nikov, Вы писали: N>Ну тогда еще тренировочные задачки N>3) Написать функцию fpower :: Int -> (a -> a) -> (a -> a), которая возводит функцию в указанную степень. Например fpower 3 (*2) должно вернуть функцию эквивалентную троекратному применению (*2), то есть (*2).(*2).(*2) или (*8). Спасибо, nikov! Отлично голову поломал Можно ли короче и более читабельно на F#?
p.s. Я правильно понимаю, что в Хаскеле вместо << юзают flip (.)? Не нашёл в Prelude аналогичного << оператора... Develop with pleasure! |
| Re: [Haskell] point-free - этюды | |
| От: | lomeo | ||
| Дата: | 16.10.09 07:07 |
| Здравствуйте, nikov, Вы писали: N>А по-моему всё предельно понятно. Почему бы так не написать? Мне тоже сразу придумался именно этот код. Для тебя. Мне сложнее, смотри.
Функция двух аргументов — композиция — функция двух аргументов. Да, понятно, т.к. использовал очень часто. Но не предельно, т.е. не интуитивно. Поэтому стараюсь писать map (\x -> (i,x)), а так как количество вложенности лямбд превышает один уровень, то именую и выношу в where. Конечная запись кажется гораздо понятнее
Всё это, разумеется, IMHO. Вот ещё одно IMHO: (,) мне кажется безобразным в этом случае. Когда появится сечение (i,) будет намного симпатичнее. А пока я пишу так:
|
| Re[4]: [Haskell] point-free - этюды | |
| От: | lomeo | ||
| Дата: | 16.10.09 07:21 |
| Здравствуйте, Пельмешко, Вы писали: П>Здравствуйте, nikov, Вы писали: N>>Ну тогда еще тренировочные задачки N>>3) Написать функцию fpower :: Int -> (a -> a) -> (a -> a), которая возводит функцию в указанную степень. Например fpower 3 (*2) должно вернуть функцию эквивалентную троекратному применению (*2), то есть (*2).(*2).(*2) или (*8). П>Спасибо, nikov! Отлично голову поломал П>Можно ли короче и более читабельно на F#? П>
П>
П>p.s. Я правильно понимаю, что в Хаскеле вместо << юзают flip (.)? Не нашёл в Prelude аналогичного << оператора...
Что делает (<<)? Если
то это аналог flip ($), flip id ну и всё в таком духе. Например, через foldl моё решение можно было написать так
|
| Re[4]: [Haskell] point-free - этюды | |
| От: | nikov | ||
| Дата: | 16.10.09 07:23 |
| Здравствуйте, Пельмешко, Вы писали: П>
Мои варианты на Haskell:
или
|
| Re[5]: [Haskell] point-free - этюды | |
| От: | deniok | ||
| Дата: | 16.10.09 07:34 | ||
| Оценка: | ![]() | ||
| Здравствуйте, nikov, Вы писали: N>Здравствуйте, Пельмешко, Вы писали: П>>
N>Мои варианты на Haskell: N>
N>или N>
Это похоже на рождение нового стиля, nikov-style Активное использование point-free плюс конструкции
|
| Re[6]: [Haskell] point-free - этюды | |
| От: | nikov | ||
| Дата: | 16.10.09 07:41 | ||
| Оценка: | 20 (3) | ||
| Здравствуйте, deniok, Вы писали: D>Активное использование point-free плюс конструкции D>
Для меня эти конструкции имеют довольно ясный интуитивный смысл: (.f).g это добавление преобразования f над вторым аргументом перед передачей его в функцию g (f.).g это добавление преобразования f над результатом функции g с двумя аргументами |
| Re[5]: [Haskell] point-free - этюды | |
| От: | lomeo | ||
| Дата: | 16.10.09 07:44 | ||
| Оценка: | +3 | ||
| Здравствуйте, nikov, Вы писали: N>
И это предельно понятная тебе запись?! Я чувствую себя таким крохотным по сравнению с твоей головой |
| Re[7]: [Haskell] point-free - этюды | |
| От: | lomeo | ||
| Дата: | 16.10.09 07:48 |
| Здравствуйте, nikov, Вы писали: N>(.f).g это добавление преобразования f над вторым аргументом перед передачей его в функцию g N>(f.).g это добавление преобразования f над результатом функции g с двумя аргументами Узнаю азбуку Морзе! Я бы в этом случае, скорее, воспользовался стрелками. |
| Re[6]: [Haskell] point-free - этюды | |
| От: | nikov | ||
| Дата: | 16.10.09 07:52 | ||
| Оценка: | 14 (1) | ||
| Здравствуйте, lomeo, Вы писали: N>>
L>И это предельно понятная тебе запись?! Просто я однажды объяснил себе, что такое (f.).g. Если бы тип a -> a был моноидом, то возведение в степень было бы тривиально: размножить нужное число раз и выполнить mconcat. Но т.к. replicate принимает два аргумента, то это не просто mconcat.replicate, а (mconcat.).replicate. Но на самом деле функцию еще надо завернуть в Endo, а результат развернуть. Отсюда (appEndo.).(mconcat.).(.Endo).replicate |
| Re[7]: [Haskell] point-free - этюды | |
| От: | nikov | ||
| Дата: | 16.10.09 07:59 | ||
| Оценка: | 21 (1) | ||
| Здравствуйте, nikov, Вы писали: N>(.f).g это добавление преобразования f над вторым аргументом перед передачей его в функцию g N>(f.).g это добавление преобразования f над результатом функции g с двумя аргументами Кстати, отсюда следует интересный вывод, что (f.) и (.h) коммутируют, то есть (f.).(.h) = (.h).(f.) |
| Re[7]: [Haskell] point-free - этюды | |
| От: | Пельмешко | ||
| Дата: | 16.10.09 12:41 |
| Здравствуйте, nikov, Вы писали: N>Для меня эти конструкции имеют довольно ясный интуитивный смысл: N>(.f).g это добавление преобразования f над вторым аргументом перед передачей его в функцию g N>(f.).g это добавление преобразования f над результатом функции g с двумя аргументами Вчера голову всю изломал чтобы сформулировать этот смысл, а всё так просто... Эх, в ocaml страшнее выглядит:
Develop with pleasure! |
| Re[3]: [Haskell] point-free - этюды | |
| От: | nikov | ||
| Дата: | 16.10.09 15:01 |
| Здравствуйте, nikov, Вы писали: N>Ну тогда еще тренировочные задачки Вот еще интересная задачка: 5) Написать функцию vector :: Int -> [a] -> [ [a] ], чтобы vector n xs давало всевозможные списки длиной n, у которых каждый элемент независимо пробегает значения из списка xs (вариант посложнее: функция vector должна работать, даже если xs — бесконечный список). |
| Re[4]: [Haskell] point-free - этюды | |
| От: | nikov | ||
| Дата: | 16.10.09 18:09 |
| Здравствуйте, nikov, Вы писали: N>чтобы vector n xs давало всевозможные списки длиной n, у которых каждый элемент независимо пробегает значения из списка xs Другими словами, получить все строки длиной n в алфавите xs. Наверное, было бы лучше назвать функцию strings. |
| Re[8]: [Haskell] point-free - этюды | |
| От: | deniok | ||
| Дата: | 16.10.09 18:22 | ||
| Оценка: | 1 (1) | ||
| Здравствуйте, nikov, Вы писали: N>Здравствуйте, nikov, Вы писали: N>>(.f).g это добавление преобразования f над вторым аргументом перед передачей его в функцию g N>>(f.).g это добавление преобразования f над результатом функции g с двумя аргументами N>Кстати, отсюда следует интересный вывод, что (f.) и (.h) коммутируют, то есть (f.).(.h) = (.h).(f.) И оба сводятся к тройной композиции с дыркой посередине \ g -> f . g . h
|
| Re[3]: [Haskell] point-free - этюды | |
| От: | Буравчик | ||
| Дата: | 17.10.09 21:00 | ||
| Оценка: | 1 (1) | ||
| Здравствуйте, nikov, Вы писали: Для меня этот код тоже малочитаемый N>1) Написать функцию clone, которая повторяет каждый символ в строке (или в списке) заданное число раз. Например clone 2 "abc" должно дать "aabbcc".
N>2) Написать функцию power, которая повторяет строку (или список) заданное число раз. Например power 2 "abc" должно дать "abcabc".
N>3) Написать функцию fpower :: Int -> (a -> a) -> (a -> a), которая возводит функцию в указанную степень. Например fpower 3 (*2) должно вернуть функцию эквивалентную троекратному применению (*2), то есть (*2).(*2).(*2) или (*8).
N>4) Написать функцию rotateLeft, которая производит циклическую перестановку элементов списка влево на указанное число позиций. Будет ли твой код работать, если список бесконечный? А если указанное число позиций больше, чем длина списка?
Best regards, Буравчик |
| Re[4]: [Haskell] point-free - этюды | |
| От: | Буравчик | ||
| Дата: | 17.10.09 22:19 |
| Здравствуйте, nikov, Вы писали: N>5) Написать функцию vector :: Int -> [a] -> [ [a] ], чтобы vector n xs давало всевозможные списки длиной n, у которых каждый элемент независимо пробегает значения из списка xs (вариант посложнее: функция vector должна работать, даже если xs — бесконечный список).
Best regards, Буравчик |
| Re[5]: [Haskell] point-free - этюды | |
| От: | nikov | ||
| Дата: | 18.10.09 07:33 |
| Здравствуйте, Буравчик, Вы писали: Б>
Этот вариант не работает с бесконечными списками, потому что следующий код никогда не выдаст [1,0]:
А функцию, которая работает только с конечными аргументами, можно написать гораздо короче. |
| Re[6]: [Haskell] point-free - этюды | |
| От: | Буравчик | ||
| Дата: | 18.10.09 08:59 | ||
| Оценка: | 1 (1) | ||
| Здравствуйте, nikov, Вы писали: N>А функцию, которая работает только с конечными аргументами, можно написать гораздо короче. Вот новый вариант.
Пока не работает для бесконечных списков. Но зато как укоротил ... << RSDN@Home 1.2.0 alpha 4 rev. 1218>> Best regards, Буравчик |
| Re[4]: [Haskell] point-free - этюды | |
| От: | nikov | ||
| Дата: | 18.10.09 13:25 |
| Здравствуйте, Буравчик, Вы писали: N>>1) Написать функцию clone, которая повторяет каждый символ в строке (или в списке) заданное число раз. Например clone 2 "abc" должно дать "aabbcc". Б>
Кажется, ты забыл принимать 2 в качестве параметра. Я бы написал эту функцию
N>>2) Написать функцию power, которая повторяет строку (или список) заданное число раз. Например power 2 "abc" должно дать "abcabc". Б>
Это тоже самое, что
N>>3) Написать функцию fpower :: Int -> (a -> a) -> (a -> a), которая возводит функцию в указанную степень. Например fpower 3 (*2) должно вернуть функцию эквивалентную троекратному применению (*2), то есть (*2).(*2).(*2) или (*8). Б>
Очень хорошее решение. N>>4) Написать функцию rotateLeft, которая производит циклическую перестановку элементов списка влево на указанное число позиций. Будет ли твой код работать, если список бесконечный? А если указанное число позиций больше, чем длина списка? Б>
Список не будет периодически прокручиваться при больших n. |
| Re[5]: [Haskell] point-free - этюды | |
| От: | nikov | ||
| Дата: | 18.10.09 13:38 |
| Здравствуйте, nikov, Вы писали: Ну и еще одна задачка: 6) Написать функцию tally :: Eq a => [a] -> [(a, Int)], которая подсчитает количество появлений каждого элемента в списке, одновременно удаляя дубликаты. |
| Re[6]: [Haskell] point-free - этюды | |
| От: | VoidEx | ||
| Дата: | 18.10.09 15:13 |
| Здравствуйте, nikov, Вы писали: N>Здравствуйте, nikov, Вы писали: N>Ну и еще одна задачка: N>6) Написать функцию tally :: Eq a => [a] -> [(a, Int)], которая подсчитает количество появлений каждого элемента в списке, одновременно удаляя дубликаты.
|
| Re[7]: [Haskell] point-free - этюды | |
| От: | nikov | ||
| Дата: | 18.10.09 15:59 |
| Здравствуйте, VoidEx, Вы писали: N>>6) Написать функцию tally :: Eq a => [a] -> [(a, Int)], которая подсчитает количество появлений каждого элемента в списке, одновременно удаляя дубликаты. VE>
Мой вариант:
|
| Re[6]: [Haskell] point-free - этюды | |
| От: | Буравчик | ||
| Дата: | 18.10.09 16:00 |
| Здравствуйте, nikov, Вы писали: N>6) Написать функцию tally :: Eq a => [a] -> [(a, Int)], которая подсчитает количество появлений каждого элемента в списке, одновременно удаляя дубликаты. Я не понимаю, зачем использовать pointfree где попало? Трудно читаем, трудно исправляем...
или более эффективно, но нужен Ord:
... << RSDN@Home 1.2.0 alpha 4 rev. 1218>> Best regards, Буравчик |
| Re[8]: [Haskell] point-free - этюды | |
| От: | VoidEx | ||
| Дата: | 18.10.09 16:09 |
| Здравствуйте, nikov, Вы писали: N>Мой вариант: N>
Мой вариант твоего варианта:
|
| Re[7]: [Haskell] point-free - этюды | |
| От: | VoidEx | ||
| Дата: | 18.10.09 18:58 | ||
| Оценка: | 47 (2) | ||
| Здравствуйте, Буравчик, Вы писали: Б>
|
| Re[8]: [Haskell] point-free - этюды | |
| От: | nikov | ||
| Дата: | 18.10.09 19:17 |
| Здравствуйте, VoidEx, Вы писали: VE>
Ну разве это не прекрасно? |
| Re[8]: [Haskell] point-free - этюды | |
| От: | Буравчик | ||
| Дата: | 18.10.09 19:44 |
| Здравствуйте, VoidEx, Вы писали: VE>
Согласен, так покрасивше. Но! Памяти жрет раза в два больше и работает значительно дольше Как-то понадобилась такая функция. Первая версия была именно такая, только без стрелок. Потом заменил на Map, стало лучше. Теперь исправлю на такое
... << RSDN@Home 1.2.0 alpha 4 rev. 1218>> Best regards, Буравчик |
| Re[9]: [Haskell] point-free - этюды | |
| От: | Буравчик | ||
| Дата: | 18.10.09 20:26 |
| Здравствуйте, Буравчик, Вы писали: Б>Теперь исправлю на такое
Кстати. Из такого counts легко получаем сортировку, работающую часто быстрее, чем в стандартной библиотеке.
А также замена nub. В стандартной библиотеке сложность O(n^2). Здесь O(n log n).
Но еще быстрее будет через Set:
Интересно, почему не использовали такие реализации. ... << RSDN@Home 1.2.0 alpha 4 rev. 1218>> Best regards, Буравчик |
| Re[7]: [Haskell] point-free - этюды | |
| От: | Oksana Gimmel | ||
| Дата: | 21.10.09 13:30 |
| Здравствуйте, Буравчик, Вы писали: Б>Пока не работает для бесконечных списков. Но зато как укоротил Не очень элегантно, но короче не получилось. Работает и с бесконечными списками.
asato ma sad gamaya |
| Re[6]: [Haskell] point-free - этюды | |
| От: | Кодт модератор | ||
| Дата: | 22.10.09 10:00 |
| Здравствуйте, deniok, Вы писали: D>Это похоже на рождение нового стиля, nikov-style Я вот подумал — нельзя ли припахать какой-нибудь изящные рукодельные инфиксные комбинаторы, чтобы вместо лямбды (\x y z -> f x g y h z) навалять (f `_x` g `_y` h `_z`)? ... << RSDN@Home 1.2.0 alpha 4 rev. 1237>> Перекуём баги на фичи! |
| Re[7]: [Haskell] point-free - этюды | |
| От: | deniok | ||
| Дата: | 22.10.09 17:40 |
| Здравствуйте, Кодт, Вы писали: К>Здравствуйте, deniok, Вы писали: D>>Это похоже на рождение нового стиля, nikov-style К>Я вот подумал — нельзя ли припахать какой-нибудь изящные рукодельные инфиксные комбинаторы, чтобы вместо лямбды (\x y z -> f x g y h z) навалять (f `_x` g `_y` h `_z`)? Боюсь сильно универсально не получится, из-за строгости типизации, но попробовать можно. |
| Re[8]: [Haskell] point-free - этюды | |
| От: | Кодт модератор | ||
| Дата: | 22.10.09 19:42 |
| Здравствуйте, deniok, Вы писали: К>>Я вот подумал — нельзя ли припахать какой-нибудь изящные рукодельные инфиксные комбинаторы D>Боюсь сильно универсально не получится, из-за строгости типизации, но попробовать можно. Нужно только подумать о базисе. Возможно, там будут нумерованные аналоги обоих комбинаторов — $ и . — что-нибудь типа %$, %$$, %$$$, %., %.., %... Перекуём баги на фичи! |
| Re[9]: [Haskell] point-free - этюды | |
| От: | lomeo | ||
| Дата: | 23.10.09 09:07 |
| Здравствуйте, Кодт, Вы писали: К>Нужно только подумать о базисе. Возможно, там будут нумерованные аналоги обоих комбинаторов — $ и . — что-нибудь типа %$, %$$, %$$$, %., %.., %... Второе рождение перла? |
| Re[10]: [Haskell] point-free - этюды | |
| От: | Кодт модератор | ||
| Дата: | 23.10.09 09:42 |
| Здравствуйте, lomeo, Вы писали: К>>Нужно только подумать о базисе. Возможно, там будут нумерованные аналоги обоих комбинаторов — $ и . — что-нибудь типа %$, %$$, %$$$, %., %.., %... L>Второе рождение перла? Типа того ... << RSDN@Home 1.2.0 alpha 4 rev. 1237>> Перекуём баги на фичи! |
| Re[3]: [Haskell] point-free - этюды | |
| От: | ettcat | ||
| Дата: | 25.10.09 07:32 |
| Здравствуйте, nikov, Вы писали: N>Ну тогда еще тренировочные задачки Спасибо, неплохо голову поломал. N>1) Написать функцию clone, которая повторяет каждый символ в строке (или в списке) заданное число раз. Например clone 2 "abc" должно дать "aabbcc". Нужно получить clone :: Int->[Char]->[Char] Есть replicate :: Int->a->[a]. Допустим, что есть такая f что f.replicate = clone . Тогда f :: (a->[a])->[a]->[a] — так это же concatMap (тут нам поможет hoogle). Получаем ответ:
N>2) Написать функцию power, которая повторяет строку (или список) заданное число раз. Например power 2 "abc" должно дать "abcabc". Тут хочется скомбинировать уже зарекомендовавшего себя replicate и concat. Опять нужно получить f :: (String->[String])->String->String, или ([Char]->[Char]])->[Char]->[Char]. Это уже можно переписать как ([a]->[a]])->([a]->[a]). То есть нужно сконструировать функцию, которая принимает функцию вида [a]->[a]] и выдает функицю вида [a]->[a] использую concat для катенации полученного массива. Тут можно догадаться что такая функция — это (concat .) В итоге получаем:
N>3) Написать функцию fpower :: Int -> (a -> a) -> (a -> a), которая возводит функцию в указанную степень. Например fpower 3 (*2) должно вернуть функцию эквивалентную троекратному применению (*2), то есть (*2).(*2).(*2) или (*8). Можно заметить, что эта задача похожа на предыдущую. Запишем сигнатуру так: fpower :: Int -> f ->f, причем заметим, что у нас есть операция concatf :: [f] -> f (композиция функций, concatf = foldr1 (.)) В этом случае нужно просто заменить concat из предыдущей задачи на наш concatf, и получим:
PS Последний пример явно показывает, что писать код проще чем его читать. Написать это я смог, а вот прочитать — думаю что не смог бы. |
| Re[3]: [Haskell] point-free - этюды | |
| От: | const_ptr | ||
| Дата: | 25.10.09 09:26 |
| Здравствуйте, nikov, Вы писали: N>1) Написать функцию clone, которая повторяет каждый символ в строке (или в списке) заданное число раз. Например clone 2 "abc" должно дать "aabbcc".
N>2) Написать функцию power, которая повторяет строку (или список) заданное число раз. Например power 2 "abc" должно дать "abcabc".
N>3) Написать функцию fpower :: Int -> (a -> a) -> (a -> a), которая возводит функцию в указанную степень. Например fpower 3 (*2) должно вернуть функцию эквивалентную троекратному применению (*2), то есть (*2).(*2).(*2) или (*8).
N>4) Написать функцию rotateLeft, которая производит циклическую перестановку элементов списка влево на указанное число позиций. Будет ли твой код работать, если список бесконечный? А если указанное число позиций больше, чем длина списка? N>Попробуй написать в point-free style c использованием существующих комбинаторов.
|
| Re[6]: [Haskell] point-free - этюды | |
| От: | const_ptr | ||
| Дата: | 25.10.09 15:57 |
| Здравствуйте, nikov, Вы писали: N>Здравствуйте, nikov, Вы писали: 5) Написать функцию vector :: Int -> [a] -> [ [a] ], чтобы vector n xs давало всевозможные списки длиной n, у которых каждый элемент независимо пробегает значения из списка xs (вариант посложнее: функция vector должна работать, даже если xs — бесконечный список).
N>Ну и еще одна задачка: N>6) Написать функцию tally :: Eq a => [a] -> [(a, Int)], которая подсчитает количество появлений каждого элемента в списке, одновременно удаляя дубликаты.
|