Daha büyük resmi elde etmek için Haskell Kodunun parçalarını birleştirmek


12

Bu bir yere geldi ama bunun nasıl çalıştığını bilmek istiyorum kodu:

    findIndices :: (a -> Bool) -> [a] -> [Int]
    findIndices _ [] = []
    findIndices pred xs = map fst (filter (pred . snd) (zip [0..] xs))

Çıktı: findIndices (== 0) [1,2,0,3,0] == [2,4] ; burada pred (== 0) ve xs [1,2,0,3,0]

Bazı anlayışlarımı göstereceğim:

    (zip [0..] xs)

Yukarıdaki satırın yaptığı şey, listedeki her şeye endeks koymaktır. Yukarıda verilen girdi için şöyle görünecektir: [(0,1), (1,2), (2,0), (3,3), (4,0)]

    (pred . snd)

Bunun pred (snd (x)) gibi bir şey ifade ettiğini buldum. Benim sorum, x listesi zip satırından mı yapılmış? Evet yöneliyorum ama tahminim dayanıksız.

Sonra, benim fst ve snd anlayışım. bunu biliyorum

    fst(1,2) = 1 

ve

    snd(1,2) = 2

Bu 2 komut kodda nasıl bir anlam ifade ediyor?

Filtre anlayışım, bir koşulla eşleşen öğelerin bir listesini döndürmesidir. Örneğin,

    listBiggerThen5 = filter (>5) [1,2,3,4,5,6,7,8,9,10]

verecek [6,7,8,9,10]

Haritaya ilişkin anlayışım, listedeki her öğeye bir işlev uygulamasıdır. Örneğin,

    times4 :: Int -> Int
    times4 x = x * 4
    listTimes4 = map times4 [1,2,3,4,5]

verecek [4,8,12,16,20]

Bu genel olarak nasıl çalışıyor? Sanırım şimdiye kadar bildiklerimde kapsamlı olduğumu ancak parçaları bir araya getiremediğimi düşünüyorum. Biri bana yardım edebilir mi?


7
Sadece bu soruyu okumak nadir bir zevkti demek istiyorum. "Bu kod nasıl çalışır?" sık sık soruyor, ancak nadiren askerin ne yaptığını ve anlamadığını bu açıklama seviyesiyle. Bu, sahip olduğunuz boşluklar hakkında iyi ve hedefli bir cevap yazmayı gerçekten eğlenceli hale getirir.
Daniel Wagner

Teşekkürler Daniel! Bu problemde çok zaman geçirdim ve bu yüzden yardıma ihtiyacım olan şeyi saptayabilirim.
Shreeman Gautam

@WillNess cevabının da işe yaradığını eklemek istiyorum. Gözde çok daha kolay ve anlaşılması kolaydır.
Shreeman Gautam

Yanıtlar:


2

Haskell'de şunu söylemek isteriz , türleri takip edin . Gerçekten de parçalar sanki kablodan tipe karşılık gelen tipe bağlanır:

( ilk, işlev bileşimi :

   (f >>> g) x  =  (g . f) x  =        g (f x)
   (f >>> g)    =  (g . f)    =  \x -> g (f x)

ve işlev kompozisyonu tür çıkarım kuralı :

    f        :: a -> b                   --      x  :: a
          g  ::      b -> c              --    f x  :: b
   -------------------------             -- g (f x) :: c
    f >>> g  :: a ->      c
    g  .  f  :: a ->      c

Şimdi,)

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]

yani, genel olarak,

zip  [0..] ::          [b]        ->        [(Int,b)]
filter (snd >>> pred) ::                    [(Int,b)] -> [(Int,b)]
map fst ::                                               [(Int,b)] -> [Int]
---------------------------------------------------------------------------
findIndices pred ::    [b] ->                                         [Int]

Siz istediniz, bu parçalar birbirine nasıl uyuyor?

Bu nasıl.


İle liste comprehensions , sizin fonksiyonu olarak yazılır

findIndices pred xs = [ i | (i,x) <- zip [0..] xs, pred x ]

sözde kodda şunu okur:

"Sonuç listesi içeren iher biri için (i,x)de zip [0..] xsböylepred x tutan" .

Bunu n-long'u çevirerek yapar

xs = [a,b,...,z] = [a] ++ [b] ++ ... ++ [z]

içine

  [0 | pred a] ++ [1 | pred b] ++ ... ++ [n-1 | pred z]

nerede [a | True]olduğunu [a]ve [a | False]bir [].


Oyunuzu aldınız adamım. Teşekkürler!
Shreeman Gautam

8

Bunun bir şey ifade ettiğini buldum pred (snd (x)). Benim sorum, x listesi zip satırından mı yapılmış? Evet yöneliyorum ama tahminim dayanıksız.

Yani pred . snd, demek \x -> pred (snd x). Bu temelde bir öğeyi eşleyen bir işlevx üzerinde pred (snd x).

Bu, ifadenin şöyle göründüğü anlamına gelir:

filter (\x -> pred (snd x)) (zip [0..] xs)

İşte burada xtarafından oluşturulan 2-bir demet zip. Olmadığını bilmek amacıyla Yani (0, 1), (1,2), (2, 0)vb sonucu korunur, snd xbu 2-küpe (şimdiye ikinci elemanı alacak 1, 2, 0, vb) ve kontrolpred tha eleman üzerinde tatmin veya edilmez. Memnun kalırsa elemanı korur, aksi takdirde eleman (2-demet) filtrelenir.

Yani eğer (== 0)bir predicate, ardından filter (pred . snd) (zip [0..] xs)2-dizilerini içerecektir[(2, 0), (4, 0)] .

Ama şimdi sonuç 2 tuple'nin bir listesi. Endeksleri istiyorsak, bir şekilde 2 demetten ve bu 2 demetin ikinci elementinden kurtulmamız gerekiyor. Bunun fst :: (a, b) -> aiçin kullanıyoruz: Bu, ilk öğesinde 2 bir demet eşleştirir. Listesi için Yani [(2, 0), (4, 0)], map fst [(2, 0), (4, 0)]dönecektir [2, 4].


1
Hey Willem, ne güzel bir açıklama! Şimdi tam kodu anladım. Teşekkürler bayım!
Shreeman Gautam
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.