Что является ярким примером того, что может быть сделано со списком, сложным с функциями высокого порядка? - программирование
Подтвердить что ты не робот

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

Я слышал от многих Pythonists, что они предпочитают понимание списков, потому что они могут делать все, что вы можете сделать, используя функции высокого порядка, такие как фильтр и сокращение, и. Итак, этот вопрос обращается к ним: что является убедительным примером того, что вы можете с ними сделать, это сложно сделать с HOF?

4b9b3361

Ответ 1

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

Учитывая понимание списка следующим образом:

[(x, y) | x <- [1..3], y <- [4..6]]

Haskell desugars:

concatMap (\x -> concatMap (\y -> [(x, y)]) [4..6]) [1..3]

Аналогично, если вы введете предикаты, например:

[(x, y) | x <- [1..3], y <- [4..6], x + y /= 5]

... затем это desugars для:

concatMap (\x -> concatMap (\y -> if (x + y) == 5 then [(x, y)] else []) [4..6]) [1..3]

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

Ответ 2

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

Возьмем этот код Python:

[(x,y) for x,y in zip(xrange(20), xrange(20, 0, -1)) if x % 2 == 0 and y % 2 == 0]

Все, что он делает, это распечатать это:

[(0, 20), (2, 18), (4, 16), (6, 14), (8, 12), (10, 10), (12, 8), (14, 6), (16, 4), (18, 2)]

Здесь эквивалентная версия с фильтром:

filter(lambda ns : ns[0] % 2 == 0 and ns[1] % 2 == 0, zip(xrange(20), xrange(20, 0, -1)))

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

Но посмотрим на эквивалентную версию в Haskell:

[(x,y) | (x,y) <- zip [0..20] [20,19..0], x `mod` 2 == 0 && y `mod` 2 == 0]

Хорошо, так же хорошо, как и версия Python. Как насчет эквивалентной версии фильтра?

import Data.Function
let f = (&&) `on` (==0) . (`mod` 2)
filter (uncurry f) $ zip [0..20] [20,19..0]

Хорошо, нам пришлось делать импорт, но код (imo) намного яснее, когда вы понимаете, что он делает, хотя некоторые люди могут по-прежнему предпочитать f для указания или даже лямбда с фильтром. По-моему, беспутная версия более кратка и концептуально понятна. Но главное, что я хочу сделать, это то, что на Python это не будет ясно из-за невозможности частично применить функции без привлечения отдельной библиотеки и отсутствия оператора композиции, поэтому в Python это хорошая идея, чтобы предпочесть понимание списков по карте/фильтру, но в Haskell он может идти в любом случае в зависимости от конкретной проблемы.

Ответ 3

В Haskell в списках понимаются "синтаксический сахар" для условностей и функций (или могут быть тривиально переведены в нотацию и затем условно удалены). Вот "официальное" руководство по их переводу: http://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-420003.11

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

Ответ 4

Другие правильны; что они не позволяют лучше манипулировать последовательностями, по сравнению с такими функциями, как map, reduce, filter и т.д. На самом деле они не рассматривали ваш вопрос о том, почему программисты Python несут в себе переполнения списков на более высокие функции порядка.

Причина, по которой Python защищает это, и программисты Python используют их, объясняется тем, что согласно Guido, создатель языка, понимание списков (и множество понятий и сжатий dict и выражений генератора) легче читать и писать, чем функциональные выражения. Философия Python заключается в том, что читаемость превосходит все.

Guido не любит конструкторы функционального программирования в целом и опасается добавления синтаксиса lambda. Это всего лишь вопрос стиля и вкуса, а не выразительности или власти. Его мнения формируют Python и как он написан.

Подробнее см. предложение Guido об удалении lambda, map, filter и reduce из Python 3 и выше. Он не был реализован (за исключением удаления reduce, который больше не является встроенной функцией), но он излагает свои рассуждения здесь: http://www.artima.com/weblogs/viewpost.jsp?thread=98196

Он суммирует это следующим образом:

фильтр (P, S) почти всегда записывается более четко, как [x для x в S, если P (x)], и это имеет огромное преимущество в том, что наиболее распространенные способы использования включают предикаты, которые являются сравнениями, например. x == 42, и определение лямбда для этого требует гораздо больше усилий для читателя (плюс лямбда медленнее, чем понимание списка).

Ответ 5

сравнить

    [[x*x, x*x+x ..] | x <- [2..]]

и

    map (\x-> map (*x) $ enumFrom x) $ enumFrom 2

Первое, очевидно, более читаемо. Вы спросили "сложно", а не "невозможно". И с filter нет ничего, чтобы указать, будем ли мы фильтровать или исключать элементы, которые проходят или терпят неудачу, данному тесту. С LC визуально проявляется.

Поэтому всякий раз, когда есть формулировка LC, это предпочтительнее ИМО, только для ее удобочитаемости. Синтаксис Haskell LC особенно краток и ясен, яснее, чем Python IMO (меньше шума). Позор не использовать.:)