web-dev-qa-db-fra.com

Combiner des fragments de code Haskell pour avoir une vue d'ensemble

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?

12
Shreeman Gautam

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]

[a | True] est [a] et [a | False] est [].

2
Will Ness