Rendern von Werten in Elemente und Zwischenelemente in Haskell

Dec 21 2020

Während der Programmierung der Benutzeroberfläche muss ich häufig eine Liste von Werten rendern und einige verwandte Informationen zwischen den gerenderten Werten hinzufügen. Im folgenden Codebeispiel rendere ich numerische Werte in Zeichenfolgen, die in Klammern stehen, und rendere den Abstand zweier Werte in eine Zeichenfolge, die zwischen den Darstellungen der Werte platziert wird. Der Code funktioniert, aber ich frage mich, ob eine Implementierung der mysteryFunktion als Teil der Haskell-Standardbibliothek verfügbar ist. Ich interessiere mich auch für Namen, die für diese Funktion in anderen Bibliotheken verwendet werden, da die Verwendung von lesbaren Wörtern das Googeln erleichtert.

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)"

Antworten

3 DDub Dec 21 2020 at 06:11

Ihre mysteryFunktion erledigt tatsächlich ein paar Dinge gleichzeitig, und wenn Sie die Verhaltensweisen trennen, ist es möglicherweise etwas einfacher zu sehen, was los ist.

Zunächst ordnen Sie nalle Elemente zu. Wir können das schreiben als fmap n xs. Als Nächstes erstellen Sie neue Elemente d x yfür alle Paare benachbarter Elemente xund y. Wir können das schreiben als zipWith d xs (tail xs).

Der letzte Schritt besteht darin, diese beiden Konstruktionen zu erstellen und eine neue Liste mit Elementen zu erstellen, die sich zwischen ihnen hin und her abwechseln. Interessanterweise war dies eine Frage, die vor 9 Jahren gestellt wurde , aber immer noch keine besonders zufriedenstellende Antwort hat. Die wahrscheinlich einfachste Antwort besteht darin, Ihre eigene Funktion zu definieren:

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

Dann können wir mysteryals Einzeiler definieren:

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

Wenn Sie wirklich wollen , dass es einen Einzeiler sein, das Beste , was ich tun konnte, wurde mit concatund transposein einem bisschen eine flippigen Art und Weise:

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

Grundsätzlich erstellen wir Singleton-Listen aus den beiden Komponenten pure, indem wir sie miteinander verschmelzen <>, dann transposediese "Liste der Listen" erstellen, um die Elemente richtig zu verteilen, und concatdas Ergebnis erstellen.