Haskell'de değerlerin öğelere ve ara öğelere dönüştürülmesi

Dec 21 2020

Kullanıcı arabirimi programlaması yaparken, sık sık bir değerler listesi oluşturma ve işlenen değerler arasına bazı ilgili bilgileri ekleme ihtiyacıyla karşılaşıyorum. Aşağıdaki kod örneğinde, sayısal değerleri parantez içinde göründükleri dizelere dönüştürüyorum ve iki değerin mesafesini, değerlerin renderları arasına yerleştirilen bir dizeye dönüştürüyorum. Kod çalışıyor, ancak mysteryişlevin bir uygulamasının Haskell standart kitaplığının bir parçası olarak mevcut olup olmadığını merak ediyorum . Ayrıca, bu işlev için diğer kütüphanelerde kullanılan isimlerle de ilgileniyorum, çünkü insan tarafından okunabilir sözcükler kullanmak Google'da aramayı kolaylaştırıyor.

mystery :: (a -> b) -> (a -> a -> b) -> [a] -> [b]
mystery n d [] = []
mystery n d [x] = [n x]
mystery n d (x:xs) = (n x) : (d x (head xs)) : mystery n d xs

node x = "(" ++ show x ++ ")"
distance x y = "-" ++ (show $ abs $ x - y) ++ "-"
render xs = concat $ mystery node distance xs
-- render [25, 68, 54, 15] == "(25)-43-(68)-14-(54)-39-(15)"

Yanıtlar

3 DDub Dec 21 2020 at 06:11

Sizin mysteryişlevi aslında aynı anda birkaç şey yapıyor ve davranışları ayırmak, eğer neler görmek için biraz daha kolay olabilir.

İlk olarak, ntüm unsurları eşleştiriyorsunuz . Bunu olarak yazabiliriz fmap n xs. Ardından, d x ytüm bitişik öğe çiftleri için yeni öğeler oluşturuyorsunuz xve y. Bunu olarak yazabiliriz zipWith d xs (tail xs).

Son adım, bu iki yapıyı alıp aralarında gidip gelen unsurların yer aldığı yeni bir liste yapmaktır. İlginç bir şekilde, bu 9 yıl önce sorulan bir soruydu , ancak yine de süper tatmin edici bir cevabı yok. Muhtemelen en basit cevap kendi işlevinizi tanımlamaktır:

alternate [] ys = ys
alternate (x:xs) ys = x : alternate ys xs

Daha sonra mysterytek satırlık olarak tanımlayabiliriz :

mystery n d x = alternate (fmap n x) (zipWith d x (tail x))

Eğer varsa gerçekten bunun tek astar olmak istiyorum, en iyi ben kullanıyordum ile gelebilir concatve transposekorkak bir şekilde bu aralar biraz:

mystery n d x = concat $ transpose $ (pure $ fmap n x) <> (pure $ zipWith d x (tail x))

Temel olarak, iki bileşenden tekil listeler yapıyoruz pure, bunları kullanarak , bunları birleştiriyoruz <>, sonra transposeöğeleri düzgün bir şekilde serpiştirmek için bu "liste listesi" ni oluşturuyoruz ve concatsonucu elde ediyoruz .