Rendu des valeurs en éléments et éléments intermédiaires dans Haskell
Lors de la programmation de l'interface utilisateur, je rencontre souvent le besoin de rendre une liste de valeurs et d'ajouter des informations connexes entre les valeurs rendues. Dans l'exemple de code suivant, je rend les valeurs numériques dans des chaînes où elles apparaissent entre parenthèses et rendent la distance de deux valeurs dans une chaîne qui est placée entre les rendus des valeurs. Le code fonctionne mais je me demande si une implémentation de la mystery
fonction est disponible dans le cadre de la bibliothèque standard Haskell. Je suis également intéressé par les noms utilisés pour cette fonction dans d'autres bibliothèques, car l'utilisation de mots lisibles par l'homme facilite la recherche sur Google.
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)"
Réponses
Votre mystery
fonction fait en fait plusieurs choses à la fois, et si vous séparez les comportements, il peut être un peu plus facile de voir ce qui se passe.
Tout d'abord, vous mappez n
sur tous les éléments. Nous pouvons écrire cela comme fmap n xs
. Ensuite, vous construisez de nouveaux éléments d x y
pour toutes les paires d'éléments adjacents x
et y
. Nous pouvons écrire cela comme zipWith d xs (tail xs)
.
La dernière étape consiste à prendre ces deux constructions et à faire une nouvelle liste avec des éléments qui alternent entre elles. Fait intéressant, c'était une question posée il y a 9 ans , mais elle n'a toujours pas de réponse très satisfaisante. La réponse la plus simple est probablement de définir votre propre fonction:
alternate [] ys = ys
alternate (x:xs) ys = x : alternate ys xs
Ensuite, nous pouvons définir mystery
comme un one-liner:
mystery n d x = alternate (fmap n x) (zipWith d x (tail x))
Si vous voulez vraiment que ce soit un one-liner, le mieux que je puisse trouver était d'utiliser concat
et transpose
d'une manière un peu funky:
mystery n d x = concat $ transpose $ (pure $ fmap n x) <> (pure $ zipWith d x (tail x))
Fondamentalement, nous créons des listes de singleton à partir des deux composants en utilisant pure
, en les fusionnant avec <>
, puis en transpose
créant cette "liste de listes" pour obtenir les éléments correctement intercalés et en concat
obtenant le résultat.