#haskell
#haskell
Вопрос:
Как я могу реализовать функцию длины в Haskell, используя понимание списка? Пример.
take [x| x<- [1,2,3], even]
Комментарии:
1. Что такое ‘обозначение zf’? Это, конечно, не тот термин, о котором я знаю. Кроме того, имеет ли ваш пример кода какое-либо отношение к вашему вопросу?
2. Вы не можете реализовать
length
функцию, используя понимание списка. Понимание списка может создать только список!3. @bradrn, может быть, это относится к сходству между нотацией для понимания списков и пониманием множеств в (например, в теории множеств Цермело-Френкеля)?
4. @dfeuer Вы могли бы сделать что-то хакерское
-XParallelListComp
? Но да, это не то, что вы можете сделать в ‘традиционном’ понимании списков.5.
[ () | _ <- xs ]
возвращает длину списка в унарной записи . Так же[ x | x <- xs ]
, как и or простоxs
.
Ответ №1:
Как указано в комментариях, если вы хотите получить целое число в качестве выходных данных, невозможно вычислить длину списка, используя только понимание списка, потому что понимание списка создает список. Однако есть несколько способов использовать понимание списка и дополнительную функцию для получения длины. Классический способ сделать это был
length x =
sum [ 1 | _ <- x ]
Это заменяет каждый элемент в списке на 1
, а затем принимает сумму.
Еще один несколько прямой способ сделать это:
length x =
last [ i | (_, i) <- zip (undefined : x) [0 ..] ]
Здесь мы расширяем список на 1, заменяем каждый элемент в списке его индексом, используя понимание списка, и берем последний индекс. Вы также можете заменить maximum
вместо last
, и это будет работать.
Есть и гораздо более экзотические способы, о которых можно пофантазировать
length x =
foldr ($) 0 [ ( 1) | _ <- x ]
но их слишком много, чтобы я мог перечислить.
В целом, это, вероятно, не очень идиоматичный или практичный способ получить длину списка. Помимо первого, который я вижу в некоторых контекстах, я не думаю, что кто-нибудь будет реализовывать длину любым из этих способов.