Tüm veri yapısını değiştirmek ve buradaki bazı öğeleri değiştirmek istiyorsunuz. Bu, genellikle veri yapısını bir parametre olarak alan ve , yapının yeni, değiştirilmiş sürümünü döndüren bir işlev tarafından yapılır.
Her giriş durumu için, bu işlev, döndürülen yeni değerin nasıl görüneceğini tanımlar.
(DataA
değerlerin bir liste olan) bir Tree
değiştirir temel işlevi muhtemelen sadece modifiye değerlerin yeni bir liste dönmelidir.
-- # function to change a |Tree|
mutate :: Tree -> Tree
mutate as = map mutateA as
-- # (The |map| function applies the |mutateA| function to every
-- # element of |as|, creating a list of all the return values)
Şimdi mutateA
fonksiyon tüm olası DataA
değerlerini değiştirmek için tanımlanması gerekir ve öyle iyi: Biz bir modifyA
işlevine değerlerin bu modifikasyonları erteleme ise ana değişiklik işlevi şöyle DataB
değerlerini işleyen mutateB
işleviyle birlikte.
Bu fonksiyonlar uygun yeni değerler değerlerin farklı olası durumlarda bakıp dönüş:
-- # function to change |DataA| items
mutateA :: DataA -> DataA
-- # A |DataA1| is a |DataA1| with modified values
mutateA (DataA1 bs) = DataA1 (map mutateB bs)
-- # A |DataA3| is a |DataA3| with modified values
mutateA (DataA3 s as) = DataA3 s (map mutateA as)
-- # In the remaining case(s) the value stays the same
mutateA d = d
-- # function to change |DataB| items
mutateB :: DataB -> DataB
mutateB (DataB1 as) = DataB1 (map mutateA as)
mutateB (DataB3 s bs) = DataB3 s (map mutateB bs)
-- # Here comes a real change
mutateB (DataB2 _) = DataB2 "foo"
yeni eleman nerede tüm DataB2
değerleri her yerde, hesaplanan ağaçtaki her element için bu yolu ağacında "foo" ile değiştirilir.
Nispeten ayrıntılıdır, çünkü içinden geçilmesi gereken bir değer içeren listesini içeren beş farklı vakanız vardır, ancak bu Haskell'e özgü değildir. 'da zorunlu bir dil, genellikle 'un map
numaralı telefonunun yerine beş adet döngüye sahip olacaktır.
Belki bu "yükü" azaltmak için veri yapınızı basitleştirebilirsiniz.Bu tabi ki gerçek kullanım durumunuza bağlıdır, ancak, örneğin, Data2
kasalarına ihtiyacınız yoktur: DataA2 "abc"
ve DataA3 "abc" []
arasında bir fark var mı?
Teşekkürler. Aradığım şey bu. Bunu işe almak için, Data.Generics'i içe aktarmam gerekiyordu – Chris
Haklısınız, kötüyüm! Cevabım düzeltildi. Teşekkürler. – Martijn
Parlak. Burada birileri SYB'nin nasıl çalıştığını biliyor. +1 –