Объясните, плс, где применяется карринг. На простых примерах. Лучше — на императивном языке или псевдоязыке. В форуме полне постов, где упоминается карринг, но... непонятно.
Что это такое, в принципе, понимаю:
f: (a, b) -> c
карринг сделает:
f: a -> b -> c
Теперь бы понять, зачем оно применяется. И ещё маленький вопрос, тут предполагается, что а и b обязательно функции?
V>Теперь бы понять, зачем оно применяется. И ещё маленький вопрос, тут предполагается, что а и b обязательно функции?
Легкий способ использования HOF. Сразу два карринга: increment_them_all = map (1+) — map f (отсутствует список) и (1+) (отсутствует второй операнд сложения). Сравни с increment_the_all_explicitly list = map (\x -> 1+x) list
Вывод типов в системе с каррингом слегка удобнее.
Yours truly, Serguey Zefirov (thesz NA mail TOCHKA ru)
Здравствуйте, voxel3d, Вы писали:
V>Объясните, плс, где применяется карринг.
В Haskell, OCaml, лямбда-исчислении.
Вопрос поставлен не совсем правильно. Карринг не применяется для решения каких-то задач. Это просто один из способов представить функцию нескольких аргументов как функцию одного аргумента.
Здравствуйте, <Аноним>, Вы писали:
А> А что, разве не так?
Не так.
А> Вместо одной аксиомы для типа 'a -> 'b нужен набор аксиом для n-арных функций.
Нет тут никаких проблем. Вывод типов усложняется перегрузкой и приведением типов. Но к карингу это отношения не имеет. К тому же есть системы обеспечивающие вывод типов и при этих препятсвиях.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, <Аноним>, Вы писали:
А>> Ну и примитивные применения: map ((*) 2) [1..10], и типа того.
VD>Ну, и чем это более понятно чем: VD>
VD>[1..10].Map(_ * 2)
VD>
VD>?
О! Теперь понятно что аноним написал
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Здравствуйте, Аноним, Вы писали:
А> Ну и примитивные применения: map ((*) 2) [1..10], и типа того.
Но чтобы поделить на 2 уже придется делать map (flip (/) 2) [1..10].
Здравствуйте, Трурль, Вы писали:
А>> Ну и примитивные применения: map ((*) 2) [1..10], и типа того. Т>Но чтобы поделить на 2 уже придется делать map (flip (/) 2) [1..10]
Можно просто map (/ 2) [1..10], (/ 2) равнозначно (flip (/) 2).
Здравствуйте, Vermicious Knid, Вы писали:
VK>Можно просто map (/ 2) [1..10], (/ 2) равнозначно (flip (/) 2).
Можно. Но это как раз и означает, что просто карринг не всегда удобно. Потребовался дополнительный сахар. Компилятор "знает" про flip, что, вообще говоря, некрасиво.
Здравствуйте, Vermicious Knid, Вы писали:
А>>> Ну и примитивные применения: map ((*) 2) [1..10], и типа того. Т>>Но чтобы поделить на 2 уже придется делать map (flip (/) 2) [1..10] VK>Можно просто map (/ 2) [1..10], (/ 2) равнозначно (flip (/) 2).
Вы бы пояснили смысл сказанного вами. А то боюсь, что многие не поняли что такое flip и зачем он нужен, но спросить стесняются.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Vermicious Knid, Вы писали:
А>>>> Ну и примитивные применения: map ((*) 2) [1..10], и типа того. Т>>>Но чтобы поделить на 2 уже придется делать map (flip (/) 2) [1..10] VK>>Можно просто map (/ 2) [1..10], (/ 2) равнозначно (flip (/) 2).
VD>Вы бы пояснили смысл сказанного вами. А то боюсь, что многие не поняли что такое flip и зачем он нужен, но спросить стесняются.
Смысл такой, что ((*) 2) не аналогично твоему (_ * 2). Оно аналогично (2 * _) (Хоть для чисел результат и будет одинаковым).
Для того, чтобы поменять местами первые два аргумента используется функция flip, т.е. (flip(f))(x,y) = f(y,x). На самом деле (/2) о flip не знает, но занимается тем же самым, т.е. создаёт лямбду (\x -> x / 2), впрочем (100/) тоже возвратит результат как лямбду (\x -> 100 / x), так что flip тут не при чём, это стандартный сахар Хаскеля для infix записи.
Что касается темы (карринг), то тут уже советовали посмотреть на Parsec. Тогда его преимущества (карринга) сразу станут видны — это краткость и понятность записи.
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, Vermicious Knid, Вы писали:
А>>>> Ну и примитивные применения: map ((*) 2) [1..10], и типа того. Т>>>Но чтобы поделить на 2 уже придется делать map (flip (/) 2) [1..10] VK>>Можно просто map (/ 2) [1..10], (/ 2) равнозначно (flip (/) 2).
VD>Вы бы пояснили смысл сказанного вами. А то боюсь, что многие не поняли что такое flip и зачем он нужен, но спросить стесняются.
Ща попробую, как тут обычно делают
OCaml:
let rec flip f b a = f a b
Haskell:
flip f b a = f a b
Nemerle:
def flip (f,b,a)
f(a,b)
Scheme:// тут не уверен ;)
(define (flip f b a) (f a b))
// ну и попробую пожалуйErlang:
flip( f, b, a ) -> f( a, b )
ie wrote: > > Ща попробую, как тут обычно делают > [ccode] > OCaml: > > let rec flip f b a = f a b
rec лишний > > Haskell: > > flip f b a = f a b > > Nemerle: > > def flip (f,b,a) > f(a,b) >
Скорее def flip (f) = fun (x,y) { f(y, x) }
Кстати, пример очень в тему, показывает, чем отличаются языки с
каррингом от языков без . > Scheme: > // тут не уверен > (define (flip f b a) (f a b))
аналогично случаю Nemerle. > // ну и попробую пожалуй > Erlang:
Аналогично случаю Nemerle.