Haskellで値をアイテムと中間アイテムにレンダリングする
ユーザーインターフェイスプログラミングを行っているときに、値のリストをレンダリングし、レンダリングされた値の間にいくつかの関連情報を追加する必要があることがよくあります。次のコード例では、数値を括弧内に表示される文字列にレンダリングし、2つの値の距離を値のレンダリングの間に配置される文字列にレンダリングしています。コードはmystery
機能しますが、関数の実装がHaskell標準ライブラリの一部として利用できるかどうか疑問に思っています。人間が読める単語を使用するとグーグルが簡単になるため、他のライブラリでこの関数に使用される名前にも興味があります。
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)"
回答
あなたのmystery
関数は、実際には、一度にカップルの事をやっている、とあなたが行動を分離すれば、何が起こっているかを確認するために少し簡単かもしれません。
まず、n
すべての要素にマッピングします。それをと書くことができますfmap n xs
。次に、d x y
隣接する要素x
とのすべてのペアに対して新しい要素を作成しますy
。それをと書くことができますzipWith d xs (tail xs)
。
最後のステップは、これら2つの構造を採用し、それらの間を行き来する要素を含む新しいリストを作成することです。興味深いことに、これは9年前に尋ねられた質問でしたが、それでも非常に満足のいく答えはありません。おそらく最も簡単な答えは、独自の関数を定義することです。
alternate [] ys = ys
alternate (x:xs) ys = x : alternate ys xs
次に、mystery
ワンライナーとして定義できます。
mystery n d x = alternate (fmap n x) (zipWith d x (tail x))
あなたがいる場合、実際にそれがワンライナーになりたい、最善の私が使っていたとまで来ることができましたconcat
し、transpose
ファンキーな方法のビットで:
mystery n d x = concat $ transpose $ (pure $ fmap n x) <> (pure $ zipWith d x (tail x))
基本的に、を使用して2つのコンポーネントからシングルトンリストを作成し、pure
それらをと融合し<>
、transpose
この「リストのリスト」を使用して要素を適切に散在させ、concat
結果を取得します。