C'est le code sur lequel je suis tombé quelque part mais je veux savoir comment cela fonctionne:
findIndices :: (a -> Bool) -> [a] -> [Int]
findIndices _ [] = []
findIndices pred xs = map fst (filter (pred . snd) (Zip [0..] xs))
Sortie: findIndices (== 0) [1,2,0,3,0]
== [2,4]
, où pred
est (==0)
& xs
est [1,2,0,3,0]
Je vais montrer une partie de ma compréhension:
(Zip [0..] xs)
Ce que fait la ligne ci-dessus, c'est mettre des indices sur tout ce qui se trouve dans la liste. Pour l'entrée donnée ci-dessus, cela ressemblerait à ceci: [(0,1),(1,2),(2,0),(3,3),(4,0)]
.
(pred . snd)
J'ai trouvé que cela signifie quelque chose comme pred (snd (x))
. Ma question est, est-ce que x
est la liste faite à partir de la ligne Zip
? Je penche vers oui mais ma supposition est fragile.
Ensuite, est ma compréhension de fst
et snd
. je le sais
fst(1,2) = 1
et
snd(1,2) = 2
Comment ces deux commandes ont-elles un sens dans le code?
Ma compréhension de filter
est qu'elle renvoie une liste d'éléments qui correspondent à une condition. Par exemple,
listBiggerThen5 = filter (>5) [1,2,3,4,5,6,7,8,9,10]
donnerait [6,7,8,9,10]
Ma compréhension de la carte est qu'elle applique une fonction à chaque élément de la liste. Par exemple,
times4 :: Int -> Int
times4 x = x * 4
listTimes4 = map times4 [1,2,3,4,5]
donnerait [4,8,12,16,20]
Comment cela fonctionne-t-il globalement? Je pense avoir été complet dans ce que je sais jusqu'à présent, mais je ne peux pas tout à fait rassembler les morceaux. Quelqu'un peut-il m'aider?
En Haskell, nous aimons dire, suivez les types. En effet les pièces se connectent comme par des fils allant du type au type correspondant:
(first, composition de la fonction est:
(f >>> g) x = (g . f) x = g (f x)
(f >>> g) = (g . f) = \x -> g (f x)
et règle d'inférence de type de composition de fonction est:
f :: a -> b -- x :: a
g :: b -> c -- f x :: b
------------------------- -- g (f x) :: c
f >>> g :: a -> c
g . f :: a -> c
Maintenant, )
findIndices :: (b -> Bool) -> [b] -> [Int]
findIndices pred = \xs -> map fst ( filter (pred . snd) ( Zip [0..] xs ))
= map fst . filter (pred . snd) . Zip [0..]
= Zip [0..] >>> filter (snd >>> pred) >>> map fst
---------------------------------------------------------------------------
Zip :: [a] -> [b] -> [(a, b)]
Zip [0..] :: [b] -> [(Int,b)]
---------------------------------------------------------------------------
snd :: (a,b) -> b
pred :: b -> Bool
------------------------------------
(snd >>> pred) :: (a,b) -> Bool
---------------------------------------------------------------------------
filter :: (t -> Bool) -> [t] -> [t]
filter (snd >>> pred) :: [(a,b)] -> [(a,b)]
filter (snd >>> pred) :: [(Int,b)] -> [(Int,b)]
---------------------------------------------------------------------------
fst :: (a, b) -> a
map :: (t -> s) -> [t] -> [s]
map fst :: [(a,b)] -> [a]
map fst :: [(Int,b)] -> [Int]
donc, dans l'ensemble,
Zip [0..] :: [b] -> [(Int,b)]
filter (snd >>> pred) :: [(Int,b)] -> [(Int,b)]
map fst :: [(Int,b)] -> [Int]
---------------------------------------------------------------------------
findIndices pred :: [b] -> [Int]
Vous avez demandé, comment ces pièces s'assemblent-elles?
C'est ainsi.
Avec list comprehensions, votre fonction s'écrit
findIndices pred xs = [ i | (i,x) <- Zip [0..] xs, pred x ]
qui dans le pseudocode lit:
"la liste de résultats contient i
pour chaque (i,x)
dans Zip [0..] xs
tel que pred x
tient ".
Il le fait en tournant le n
- long
xs = [a,b,...,z] = [a] ++ [b] ++ ... ++ [z]
dans
[0 | pred a] ++ [1 | pred b] ++ ... ++ [n-1 | pred z]
où [a | True]
est [a]
et [a | False]
est []
.