2013-07-27 17 views
6

Haskell için çok yeni ve kendi ters işlevimi oluşturmaya çalışıyor. Bu burada yazdım, ama her zaman boş bir liste [] döndürür:Haskell tersine çevirme işlevi

reverse' :: [a] -> [a] 
reverse' xs = [xs !! k | k <- [((length xs) - 1)..0]] 

kimse yanlış yapıyorum açıklayabilir misiniz?

Teşekkür

+5

yapar '[uzunluğu xs - 1, uzunluk xs - 2..0]' çalışma? –

+1

Yine de özyinelemeden rahat değilseniz, diğer uygulamalara bakmadan önce, aşağıdakileri doldurarak başka bir yolu tersine çevirmeyi deneyin: 'reverse [] = ...; = ... ': (xs x) ve olarak düşünmek "... boş listenin tersidir ve listeyle consed x' 'ters' xs' olduğunu ..." bu kadar – jberryman

+3

Not olduğunu ters listelere genel olarak indeksle erişilebiliyor. Özel olarak tasarlanmıştır, böylelikle elemanlar tarafından kafa elemanlarından kolayca _recursively_, ancak rasgele pozisyonda bir eleman talep ettiğinizde çok kötü bir şekilde gerçekleştirebilirsiniz. – leftaroundabout

cevap

12

bahsedildiği groovy gibi, Haskell aralıkları çoğunlukla marjinaldir - yani, bunu biraz ipucu vermek sürece azalan listesini oluşturmak için nasıl hiçbir fikri vardır.

foo xs = [(length xs-1), (length xs -2)..0] 
rev xs = [xs !! k| k <- foo xs] 

böyle GHCi dışarı denetler:

Prelude> rev [1..5] 
[5,4,3,2,1] 

göz

Prelude> [5..0] 
[] 
Prelude> [5,4..0] 
[5,4,3,2,1,0] 

Yani, böyle bir şey inşa edebilirsiniz: Aşağıda bir GHCI oturum göz at Bir listeyi geri çevirmeyle ilgili diğer fikirler için Unexpected result while reversing a list ve How can I write reverse by foldr efficiently in Haskell? numaralı telefonlardan.

+3

Ama sen 'foo' bağlanma uzunluğunu hesaplama önlemek için where' bir' 'iki kez xs' kullanabilirsiniz – Ingo

+0

boş listesi ve tekil liste ile kontrol etmeyi unutmayın. – Jubobs

5

çoğu zaman bazı değişmeyen icat ve bunun için koruma bazı yasalar yazmak için yardımcı olur. İşte

reverse xs  = reverse xs ++ [] 
reverse (x:xs) = (reverse xs ++ [x]) ++ [] 
       = reverse xs ++ ([x] ++ []) 
       = reverse xs ++ (x:[]) 
reverse (x:(y:xs)) = 
       = reverse (y:xs) ++ (x:[]) 
       = reverse xs ++ (y:x:[]) 
...... 
reverse (x:(y:...:(z:[])...)) = 
       = reverse [] ++ (z:...:y:x:[]) 

yüzden biz hazırız

reverse xs = rev xs [] where 
    rev (x:xs) acc = rev xs (x:acc) 
    rev []  acc = acc 

tanımlarsanız dikkat edin. :) yanı, bir çağrı rev a b, a bir kafa elemanı alıp a boş ve sonra sadece b var kadar b bunu prepending bir dönüşüm altında korunur ters a ve b ait Ulama için. Bu da

{-# LANGUAGE TupleSections #-} 
reverse = snd . until (null.fst) (\(a,b)-> (tail a,head a:b)) . (, []) 

olarak, İngilizce açıklama aşağıdaki higher-order function until kullanımı ile ifade edilebilir Ayrıca, örneğin hemen tanımlayabilir diyoruz nasıl tam olarak biraz çimdik ile aynı iç işlevini kullanarak bir revappend fonksiyonu:

revappend xs ys = rev xs ys where 
    rev (x:xs) acc = rev xs (x:acc) 
    rev []  acc = acc 
0

benim şeklidir özyineleme ile kendi ters fonksiyonunu oluşturmak için. Bu işlev, bilinen işlevleri tanımlamak için çok kullanışlıdır.

list = [] reverse [x] = list ++ [x] reverse = list ++ [last l] ++ reverse (init l)

İlgili konular