2016-01-06 17 views
6

Haskell için birkaç kaynak kullanıyorum: Size bir Haskell ve wikibook öğrenin. Ancak, ben yinelemeyi biraz daha anlamanıza yardımcı olacak bir açıklama bulmaya çalışıyorum. Kısmen anladığım 'Bir Haskell'i Öğren' kitabından örnek bir kod parçası ekledim.Fonksiyonlarda Haskell özyinesini anlama

maximum' :: (Ord a) => [a] -> a 
maximum' [] = error "maximum of empty list" 
maximum' [x] = x 
maximum' (x:xs) 
    | x > maxTail = x 
    | otherwise = maxTail 
    where maxTail = maximum' xs 

Yukarıdaki kodun tamamını "maxTail = maximum" xs "satırına kadar anlıyorum. Anlamadığım şey, kodun azami değeri döndürmek için, maksimum '' çağırmaktan '' nasıl değerlendirildiğidir. Ya da maksimumun 'listenin en yüksek öğesi olduğunu bilir.

Başka bir örnek:

reverse' :: [a] -> [a] 
reverse' [] = [] 
reverse' (x:xs) = reverse' xs ++ [x] 

ters kadar herşeyi anlamak' listesinin kuyruğunda denir. Başka bir deyişle, tersinin 'kuyruk parçalarını ters çevirmesi' anlamına geldiğini nasıl biliyor.

Bir açıklama için gerçekten minnettar olurum ve eğer bu kadar basitse, bu dile yeni geldim.

+0

'reverse'' demek "kuyruk elemanları ters" değil. 'xs' tersi '' kuyruk elemanlarını ters çevir '' anlamına gelir, çünkü 'xs' kuyruk elemanlarıdır ve tersine çevirmek anlamına gelir. – immibis

+1

Özyinelemede, "maksimum" ve "geri" işlevlerinin, söz konusu listenin _tail_ (yani, ilk öğeden başka bir şey) üzerinde çağrıldığını unutmayın. 'maksimum '[1,2,3]' yinelemeli olarak listeye uygulanır [2,3] '. Tamsayıların listesinin maksimum değeri 1 olan ilk liste elemanı ve 2. listenin geri kalanının maksimum değeridir. Bir listeyi '(x: xs)' yoluyla eşleştirdiğinde, 'x 'ilk liste öğesidir ve xs' geri kalanıdır (" kuyruk "). –

+0

"Tersinin, kuyruk öğelerini ters çevirmesi anlamına geldiğini nasıl anlar". değil; ama bunu indüksiyonla kanıtlayabilirsin. '[]' Ve '[a]' vakalarıyla başlayın; sonra, [a, b] ', .... 'ye bir bakın, sonra da genel [a, b, ..., n] durumunda olduğunu varsayın ve bir sonraki olayı takip ettiğini kanıtlayın. a, b, ..., n, m], tersine dönüyor. –

cevap

11

umarım daha iyi anlamaları için, çizgiler, satır satır geçiyor: hat 1'de

1| maximum' :: (Ord a) => [a] -> a 
2| maximum' [] = error "maximum of empty list" 
3| maximum' [x] = x 
4| maximum' (x:xs) 
    | x > maxTail = x 
    | otherwise = maxTail 
    where maxTail = maximum' xs 

: Eğer bir yılların listesini almak ve bu tür bir elementi dönmek demek. Ayrıca, bu listedeki öğelerin ya da alınabilir olması gerekir, böylece bunları bir siparişe koyabilirsiniz.

Satır 2'de: giriş olarak boş bir liste alırsanız, o boş listede "en yüksek değer" bulunamayacağını ve böylece bir hatayla işlevi sonlandıracağınızı söyleyen bir kenar durumunuz vardır. .

Satır 3'te: 1 öğe içeren bir liste alırsanız, bu öğenin en yüksek öğe olması gerektiğini söyleyen başka bir kenar durumunuz vardır, böylece döndürün.

Satır 4'te: birinci öğeye (x) ve listenin kalanına (xs) uyması için desen eşleştirmesi kullanın. Daha sonra 'un maxTail'dan daha büyük olup olmadığını kontrol edin, burada maximum' işlevinin sonucu xs listesinin geri kalanıyla aranır. O xmaxTail büyükse

sonra x dönmek ve aksi maxTail den büyük x ve maxTail dönmek olduğunu.


bazı sayılarla bir örnek de burada yardımcı gerektiğini düşünüyorum:

girişi:

[2, 5, 4, 13] 

çağrı:

maximum' [2, 5, 4, 13] 

Ne olur?

İkinci örnekte 0
maximum' (x : xs) 
      ↓  ↓ 
maximum' (2:[5, 4, 13]) 
      │ 
      ↓        result 13 
    x > maxTail = x       ↑ 
    2 > maximum' [5, 4, 13] = x //2 > 13 = 13 ← ────┐ 
     │           │ 
     └ maximum' (x : xs)      │ 
         ↓ ↓       │ 
      maximum' (5:[4, 13])      │ 
         │        │ 
         ↓        ↑ 
       x > maxTail = x      │ 
       5 > maximum' [4, 13] = x //5 > 13 = 13 ← ─────┐ 
        │           │ 
        └ maximum' (x: xs)      │ 
            ↓ ↓       │ 
         maximum' (4:[13])      │ 
            │       │ 
            ↓       ↑ 
           x > maxTail = x     │ 
           4 > maximum' [13] = x //4 > 13 = 13 ┐ 
            │         │ 
            └ maximum' [x] = x    ↑ 
            maximum' [13] = 13 → ───────────┘ 

Hemen hemen aynı: hat 1'de

1| reverse' :: [a] -> [a] 
2| reverse' [] = [] 
3| reverse' (x:xs) = reverse' xs ++ [x] 

: Eğer bir yıllardan bir listesini almak ve bir yılların listesini döndürür söylerler.

Satır 2'de: Boş bir liste alırsanız, tersi listenin de boş olduğu bir kenar durumunuz vardır.

Satır 3'te: listenin ilk elemanına (x) ve kuyruğun (xs) eşleşmesi için tekrar desen eşleştirmesi kullanın.

Artık iki listeyi birlikte eklemek için ++ kullanın, bu da ters kuyruklu listenin ilk öğesidir.


Ve yine ben biraz daha anlaşılır olacak bir örnekle umut:

girişi:

[1, 2, 3] 

çağrı: ne olur

reverse' [1, 2, 3] 

:

reverse' (x : xs) 
      ↓ ↓ 
reverse' (1:[2, 3]) 
      │        result [3, 2, 1] 
      ↓          ↑ 
    (reverse' [2, 3]) ++ [1] //[3, 2] ++ [1] = [3, 2, 1] ← ────┐ 
    │               │ 
    └ reverse' (x: xs)           │ 
       ↓ ↓           │ 
     reverse' (2:[3])           │ 
       │            ↑ 
       ↓            │ 
     (reverse' [3]) ++ [2] //[3] ++ [2] = [3, 2] ← ───┐ → ┘ 
      │            │ 
      └ reverse' (x:xs)        │ 
         ↓ ↓         │ 
      reverse' (3:[])        │ 
         │         ↑ 
         ↓         │ 
       (reverse' []) ++ [3] //[] ++ [3] = [3] ┐ → ┘ 
       │          ↑   
       └ reverse' [] = [] → ──────────────────┘ 
+0

İyi bir diyagramı seviyorum. – luqui

+0

@luqui Thanks :), elimden gelenin en iyisini denedim, bu yüzden takip etmesi kolay ve anlaşılması kolay. – Rizier123

+0

Harika cevap için teşekkürler, diyagram ve arıza gerçekten bana yardımcı oldu! :) –

1

uzunluğu

length' [] = 0 

Örnek 1: Boş bir liste uzunluğu 0.

length' (x:xs) = 1 + length' xs 

Örnek 2: en az bir eleman ile bir liste uzunluğu 1'den daha daha fazla eleman kalmayıncaya kadar durum 2'nin tekrarlanması ile listenin kuyruğunun uzunluğu, tatmin edici durum 1.


Ters

reverse' [] = [] 

Durum 1: Bir liste boşsa, onun tam tersi de boş listedir.

reverse' (x:xs) = reverse' xs ++ [x] 

Durum 2: Bir listesinde en az bir eleman varsa, o zaman biz, birinci elemanı çekip sonuna kadar taşımak ve aynı kalan tersine çevirebilir dava ile listeyi geçmeden arada-by 2 hiçbir öğe 1.

reverse' [1, 2, 3] 
= 
reverse' (1 : (2 : (3 : []))) 
= 
reverse' (2 : (3 : [])) ++ [1] 
= 
reverse' (3 : []) ++ [2] ++ [1] 
= 
reverse' [] ++ [3] ++ [2] ++ [1] 
= 
[] ++ [3] ++ [2] ++ [1] 
= 
[3, 2, 1] 

Maksimum dava

maximum' [x] = x 

Durum 1 tatmin kalır sonu: bir liste onl varsa y bir eleman, bu eleman maksimumdur.

maximum' (x:xs) 

Durum 2: Bir liste daha sonra ya en az bir eleman, ...

| x > maxTail = x 

varsa ... İlki maksimum var ki bu durumda tüm diğerleri, daha büyüktür; ya ... tatmin ... tek bir eleman dek durumunda 2 ile listeyi ilerleyerek bulmak

where maxTail = maximum' xs 

... kalır

| otherwise = maxTail 

... o değil, bu yüzden maksimum tüm diğerleri en büyüğüdür vaka 1.

Ben maximum' tanımını yeniden ifade edeceğiz

daha kolay ikame ettiği göstermek için yapmak:

maximum' (x:xs) = let maxTail = maximum' xs in 
    if x > maxTail then x else maxTail 
Şimdi

:

maximum' [1, 3, 2] 
= 
maximum' (1 : (3 : (2 : []))) 
= 
let maxTail1 = maximum' (3 : (2 : [])) in 
    if 1 > maxTail1 then 1 else maxTail1 
= 
let maxTail1 = 
    (let maxTail2 = maximum' (2 : []) in 
     if 3 > maxTail2 then 3 else maxTail2) in 
    if 1 > maxTail1 then 1 else maxTail1 
= 
let maxTail1 = 
    (let maxTail2 = 2 in 
     if 3 > maxTail2 then 3 else maxTail2) in 
    if 1 > maxTail1 then 1 else maxTail1 
= 
let maxTail1 = (if 3 > 2 then 3 else 2) in 
    if 1 > maxTail1 then 1 else maxTail1 
= 
let maxTail1 = 3 in 
    if 1 > maxTail1 then 1 else maxTail1 
= 
if 1 > 3 then 1 else 3 
= 
3 
+0

Cevabınız için teşekkürler. Bunu kullanarak görmek güzeldi ve başka bir şey daha iyi anlamanıza yardımcı oldu :)! –