Este es el código que encontré en alguna parte, pero quiero saber cómo funciona esto:
findIndices :: (a -> Bool) -> [a] -> [Int]
findIndices _ [] = []
findIndices pred xs = map fst (filter (pred . snd) (zip [0..] xs))
Salida: findIndices (== 0) [1,2,0,3,0]
==[2,4]
, donde pred
es (==0)
y xs
es[1,2,0,3,0]
Mostraré algo de mi comprensión:
(zip [0..] xs)
Lo que hace la línea anterior es poner índices a todo en la lista. Para la entrada dada anteriormente, sería el siguiente: [(0,1),(1,2),(2,0),(3,3),(4,0)]
.
(pred . snd)
Descubrí que esto significa algo así pred (snd (x))
. Mi pregunta es, ¿ x
la lista está hecha desde la zip
línea? Me estoy inclinando hacia sí, pero mi suposición es débil.
A continuación, es mi comprensión de fst
y snd
. Yo sé eso
fst(1,2) = 1
y
snd(1,2) = 2
¿Cómo tienen sentido estos dos comandos en el código?
Entiendo filter
que devuelve una lista de elementos que coinciden con una condición. Por ejemplo,
listBiggerThen5 = filter (>5) [1,2,3,4,5,6,7,8,9,10]
daría [6,7,8,9,10]
Según tengo entendido, map aplica una función a cada elemento de la lista. Por ejemplo,
times4 :: Int -> Int
times4 x = x * 4
listTimes4 = map times4 [1,2,3,4,5]
daría [4,8,12,16,20]
¿Cómo funciona esto en general? Creo que he sido comprensivo en lo que sé hasta ahora, pero no puedo armar las piezas. ¿Alguien puede ayudarme?
fuente
Respuestas:
En Haskell nos gusta decir, sigue los tipos . De hecho, las piezas se conectan como si fueran cables que van del tipo al tipo correspondiente:
(primero, la composición de la función es:
y la regla de inferencia de tipo de composición de función es:
Ahora, )
entonces, en general,
Usted ha preguntado, ¿cómo encajan estas piezas?
Así es como.
Con las comprensiones de listas , su función se escribe como
que en pseudocódigo lee:
msgstr "la lista de resultados contiene
i
para cada uno(i,x)
de formazip [0..] xs
que sepred x
mantenga" .Lo hace girando el
n
largodentro
donde
[a | True]
es[a]
y[a | False]
es[]
.fuente
Bueno
pred . snd
, significa\x -> pred (snd x)
. Así que esto básicamente construye una función que mapea un elementox
depred (snd x)
.Esto significa que la expresión se ve así:
Aquí
x
hay una tupla 2 generada porzip
. Así que con el fin de saber si(0, 1)
,(1,2)
,(2, 0)
, etc., están retenidos en el resultado,snd x
se llevará el segundo elemento de estas 2-tuplas (así1
,2
,0
, etc.), y comprobar si elpred
Tha elemento se cumple o no. Si está satisfecho, retendrá el elemento; de lo contrario, ese elemento (la tupla 2) se filtrará.Entonces, si
(== 0)
es elpred
icate,filter (pred . snd) (zip [0..] xs)
contendrá las 2 tuplas[(2, 0), (4, 0)]
.Pero ahora el resultado es una lista de 2-tuplas. Si queremos los índices, de alguna manera necesitamos deshacernos de las 2 tuplas y el segundo elemento de estas 2 tuplas. Usamos
fst :: (a, b) -> a
para eso: esto asigna una tupla de 2 en su primer elemento. Entonces, para una lista[(2, 0), (4, 0)]
,map fst [(2, 0), (4, 0)]
volveremos[2, 4]
.fuente