2012-10-31 39 views
5

listelerin bir liste üzerinde çalışmak Haskell için biraz başlangıç ​​yapıyorum, bu yüzden ben katı tip şeyler ile biraz mücadele ediyorum, sadece birileri bana yardımcı olmaya çalışıyorum bir fonksiyon ile bana yardımcı olabilir eğer .Haskell

[[1,2,3], [7,6,8], [0,3,4]] 

ve öyle boyunca pozisyonların sayısına göre sonradan listeleri çeviri bir liste haline getirmektedir ekler: Temelde, örneğin, listelerin bir listesini alır. (Hataları tipi alır)

foldl (zipWith +) [] [[1,2,3],[0,7,6,8],[0,0,0,3,4]] 

İşte benim şimdiki işlevi: Yani aslında böyle bir şey yaptığını olacağını örnek listesi üzerinde çalışırken

addLists :: [[Integer]] -> [Integer] 
    addLists [[]] = [] 
    addLists [[x]] = [x] 
    addLists [x:xs] = zipWith (+) [x] ([0]++ (addLists xs)) 
+3

Lütfen, addLists [[1,2,3], [7,6,8], [0,3,4]] 'sonuçlarının ne olmasını istediğinizi belirtin. Sorunuzdan belli değil. – dave4420

+1

Sorunu açıklığa kavuşturmak için düzenlediğiniz anlaşılıyor, ama korkarım hala anlamıyorum. AddLists [[1,2,3], [7,6,8], [0,3,4]] 'nin sonucu neye benzemeli? Verdiğiniz örnek, 'katlama (zipWith +) [] [[1,2,3], [0,7,6,8], [0,0,0,3,4]]' yazmaz. kontrol et ve ne yapmak istediğini anlayamıyorum. – mhwombat

+1

Sonuçların olmasını istiyor musunuz? [1, 2 + 7, 3 + 6 + 0, 8 + 4, 4] '=' [1,9,9,12,4] '? – mhwombat

cevap

3

Bunun istediğini yapar düşünüyorum

import Data.List (transpose) 

addLists :: Num a => [[a]] -> [a] 
addLists xs = map sum . transpose $ zipWith (\n x -> replicate n 0 ++ x) [0..] xs 
+0

Teşekkürler, nasıl çalıştığını tam olarak açıklayabilir misiniz? Oldukça fazla takip edebilirim ama tam olarak değil! –

+0

@npfedwards Üzgünüm, bu cevabı geri getirmek ve genişletmek istedim, ama başka bir şey ortaya çıktı. Yakında alacak, umarım! –

+1

Biraz daha hoş: 'addLists = harita toplamı. aktar. zipWith (++) (girişler (tekrar 0)) '. İlginç kısım, "Transpose", yani "Data.List" işlevi ile aşina olmaya değer bir işlevdir. Bu bir kompozisyon olduğundan, nasıl çalıştığını anlamak için her parça ile ayrı ayrı oynayabilirsiniz. – shachaf

6

Not: ([0]++), (0:) ile aynıdır, bu da daha düzgün görünmesini ve bize nanosaniye veya iki tasarruf etmesini sağlar. (Nanosaniye şeyiyle dalga geçiyorum - hiçbir şey neyin nanosaniyenin daha hızlı olduğunu söyleyemez, ama yine de bu şekilde daha iyi olur.)

Önce size gereken listeleri hazırlayalım. Bir tanımı için yeterli bilgi var O

postponeLists [[1,2,3], [7,6,8], [10,20,30,40]] 
      = [[1,2,3], [0,7,6,8], [0,0,10,20,30,40]] 
      = [1,2,3] : ones that should have zero in front of them 

istiyorum:
postponeLists [] = [] 
postponeLists (l:ls) = l : map (0:) (postponeLists ls) 

Şimdi

foldl (zipWith +) [] [[1,2,3],[0,7,6,8],[0,0,0,3,4]] 

söyledi fakat

foldl (zipWith (+)) [] [[1,2,3],[0,7,6,8],[0,0,0,3,4]] 

ama maalesef demek, bu sanaverir 0, zipWith, listelerden herhangi biri biter bitmez durur. Onları durmayan bir şekilde sıkıştırmanın bir yoluna ihtiyacımız var.

Çözüm 1: en uzun olanı bulmak take maxlength.(++ repeat 0)
Çözüm 2'yi kullanarak hepsini o maxlength olun: durmuyor başka zipWith fonksiyonunu yazın.

zipWithMore :: (a -> a -> a) -> [a] -> [a] -> [a] 
zipWithMore f (a:as) (b:bs) = f a b : zipWithMore f as bs 
zipWithMore f []  bs  = bs -- if there's more in bs, use that 
zipWithMore f as  []  = as -- if there's more in as, use that 

Şimdi zipWithMore (+) ile zipWith (+) değiştirebilirsiniz:

Ben o sırada bitmiyor edelim en definition of zipWith

zipWith :: (a->b->c) -> [a]->[b]->[c] 
zipWith f (a:as) (b:bs) = f a b : zipWith f as bs 
zipWith _ _  _  = [] -- here's the problem - it stops as soon as any list is empty 

OK bakalım 2. çözümü tercih. Yumruk hattını sana bırakacağım.

+0

Teşekkürler, büyük yardım! –

+0

(0:) ', en azından' ghc-O2 'ile değil, herhangi bir nanosaniyeyi ([0] ++) 'üzerinden kaydetmez. '(:)' bazen *, her ikisinin de geçerli olduğu yerde (++) 'dan daha iyidir, ancak bu şekildeki gibi nanosaniye ait spekülasyonlara izin vermemelisiniz. – shachaf

+1

@shachaf Tabii ki değil! Şaka yapıyordum ki gereksiz yere "nanosaniye ya da ikiyi kurtar" diyerek işaret ediyordum. '(0:)' daha güzel ve bu alışkanlığı tanıtmak istedim. Böyle bir sorunla nanosaniye kimin umurunda? Netleştirdim, ciddi anlamda değildi. – AndrewC