Это код, который я где-то нашел, но хочу знать, как это работает:
findIndices :: (a -> Bool) -> [a] -> [Int]
findIndices _ [] = []
findIndices pred xs = map fst (filter (pred . snd) (zip [0..] xs))
Вывод: findIndices (== 0) [1,2,0,3,0]
==[2,4]
, где pred
есть (==0)
& xs
есть[1,2,0,3,0]
Я покажу некоторые из моего понимания:
(zip [0..] xs)
То, что делает вышеупомянутая строка, помещает индексы для всего в списке. Для ввода приведенного выше, это будет выглядеть следующим образом : [(0,1),(1,2),(2,0),(3,3),(4,0)]
.
(pred . snd)
Я обнаружил, что это означает что-то вроде pred (snd (x))
. У меня вопрос, x
составлен ли список из zip
линии? Я склоняюсь к да, но мое предположение неубедительно.
Далее, мое понимание fst
и snd
. я знаю это
fst(1,2) = 1
а также
snd(1,2) = 2
Как эти две команды имеют смысл в коде?
Насколько я понимаю filter
, он возвращает список элементов, которые соответствуют условию. Например,
listBiggerThen5 = filter (>5) [1,2,3,4,5,6,7,8,9,10]
даст [6,7,8,9,10]
Я понимаю, что карта применяет функцию к каждому элементу в списке. Например,
times4 :: Int -> Int
times4 x = x * 4
listTimes4 = map times4 [1,2,3,4,5]
даст [4,8,12,16,20]
Как это работает в целом? Я думаю, что я был всеобъемлющим в том, что я знаю до сих пор, но не могу собрать все воедино. Кто-нибудь может мне помочь?
Ответы:
В Хаскеле мы любим говорить, следим за типами . Действительно, части соединяются как бы проводами, идущими от типа к соответствующему типу:
(во-первых, состав функции :
и правило вывода типа композиции функции :
Сейчас же, )
так что в целом
Вы спросили, как эти части сочетаются друг с другом?
Это как.
С списком пониманий ваша функция записывается как
который в псевдокоде читает:
"список результатов содержит
i
для каждого(i,x)
в томzip [0..] xs
, чтоpred x
содержит" .Это делается путем поворота
n
-длинногов
где
[a | True]
есть[a]
и[a | False]
есть[]
.источник
Ну
pred . snd
значит\x -> pred (snd x)
. Так что это в основном создает функцию, которая отображает элементx
наpred (snd x)
.Таким образом, это означает, что выражение выглядит так:
Вот
x
, таким образом, 2-кортеж, сгенерированныйzip
. Поэтому для того , чтобы знать , если(0, 1)
,(1,2)
,(2, 0)
и т.д. сохраняются в результате,snd x
будет принимать второй элемент из этих 2-кортежей (так1
,2
,0
и т.д.), и проверить , еслиpred
на двигательный элемент удовлетворяет или нет. Если он удовлетворен, он сохранит элемент, в противном случае этот элемент (2-кортеж) отфильтровывается.Так что, если
(== 0)
этоpred
айс, тоfilter (pred . snd) (zip [0..] xs)
будет содержать 2 кортежа[(2, 0), (4, 0)]
.Но теперь результатом является список из 2-х кортежей. Если нам нужны индексы, нам как-то нужно избавиться от 2-кортежа и второго элемента этих 2-кортежей. Для этого мы используем
fst :: (a, b) -> a
: это отображает 2-кортеж на его первый элемент. Таким образом , для списка[(2, 0), (4, 0)]
,map fst [(2, 0), (4, 0)]
будет возвращаться[2, 4]
.источник