Este é o código que encontrei em algum lugar, mas quero saber como isso funciona:
findIndices :: (a -> Bool) -> [a] -> [Int]
findIndices _ [] = []
findIndices pred xs = map fst (filter (pred . snd) (zip [0..] xs))
Saída: findIndices (== 0) [1,2,0,3,0]
==[2,4]
, onde pred
está (==0)
& xs
é[1,2,0,3,0]
Vou mostrar um pouco do meu entendimento:
(zip [0..] xs)
O que a linha acima faz é colocar índices para tudo na lista. Para a entrada dada acima, que seria parecido com este: [(0,1),(1,2),(2,0),(3,3),(4,0)]
.
(pred . snd)
Eu descobri que isso significa algo como pred (snd (x))
. Minha pergunta é: x
a lista é feita a partir da zip
linha? Estou inclinado a sim, mas meu palpite é frágil.
Em seguida, é o meu entendimento de fst
e snd
. Eu sei disso
fst(1,2) = 1
e
snd(1,2) = 2
Como esses dois comandos fazem sentido no código?
Pelo que entendi, filter
ele retorna uma lista de itens que correspondem a uma condição. Por exemplo,
listBiggerThen5 = filter (>5) [1,2,3,4,5,6,7,8,9,10]
daria [6,7,8,9,10]
Meu entendimento do mapa é que ele aplica uma função a todos os itens da lista. Por exemplo,
times4 :: Int -> Int
times4 x = x * 4
listTimes4 = map times4 [1,2,3,4,5]
daria [4,8,12,16,20]
Como isso funciona em geral? Eu acho que tenho sido abrangente no que sei até agora, mas não consigo juntar as peças. Alguém pode me ajudar?
fonte
Respostas:
Em Haskell, gostamos de dizer, siga os tipos . De fato, as peças se conectam como se por fios passando do tipo para o tipo correspondente:
(primeiro, a composição da função é:
e a regra de inferência do tipo de composição de funções é:
Agora, )
então, no geral,
Você perguntou: como essas peças se encaixam?
É assim.
Com a compreensão de lista , sua função é escrita como
que em pseudocódigo diz:
"lista de resultados contém
i
para cada(i,x)
emzip [0..] xs
tal quepred x
detém" .Faz isso girando o
n
botão -longpara dentro
onde
[a | True]
está[a]
e[a | False]
está[]
.fonte
Bem
pred . snd
, significa\x -> pred (snd x)
. Portanto, este basicamente constrói uma função que mapeia um elementox
empred (snd x)
.Isso significa que a expressão se parece com:
Aqui
x
está, portanto, uma 2-tupla gerada porzip
. Portanto, a fim de saber se(0, 1)
,(1,2)
,(2, 0)
, etc. são mantidos no resultado,snd x
levará o segundo elemento destes 2-tuplas (assim1
,2
,0
, etc.), e verifique se opred
on tha elemento está satisfeito ou não. Se estiver satisfeito, ele reterá o elemento, caso contrário, esse elemento (a 2-tupla) será filtrado.Então, se
(== 0)
é opred
icate, elefilter (pred . snd) (zip [0..] xs)
conterá as 2 tuplas[(2, 0), (4, 0)]
.Mas agora o resultado é uma lista de 2 tuplas. Se queremos os índices, precisamos, de alguma forma, nos livrar da tupla 2 e do segundo elemento dessas 2 tuplas. Usamos
fst :: (a, b) -> a
para isso: isso mapeia uma 2-tupla em seu primeiro elemento. Então, para uma lista[(2, 0), (4, 0)]
,map fst [(2, 0), (4, 0)]
retornará[2, 4]
.fonte