私はHaskellが初めてで、sort
関数を使用して、最初の要素を使用してタプルのリストをソートしようとしています。もし私が持っていたら、(同じ番号の場合はアルファベット順で)の["a", "b", "a", "c", "c"]
ようなものが得られます。[(1,"b"), (2,"a"), (2,"c")]
どうすればこれを行うことができますか?私は今、完全に途方に暮れています… 私はまだ「Haskell の考え方」に入ろうとしています。
import Data.List (sort, group)
import Control.Arrow ((&&&))
answer :: Eq a => [a] -> [(Int, a)]
answer = sort . map (length &&& head) . group . sort
しかし、あなたが初心者の場合、これについて説明するのは少し難しいかもしれません。&&&
そのため、次のように書き直します。
import Data.List (sort, group)
answer :: Eq a => [a] -> [(Int, a)]
answer = sort . map f . group . sort
where f xs @ (x:_) = (length xs, x)
あなたは私がsort
2回電話していることに気付くでしょう. これは意図的なものです。
最後のsort
(左側のもの) は、タプルの出力リストを並べ替えます。たまたま、タプルの最初の要素の昇順で並べ替え、タプルの 2 番目の要素で並べ替えることで同点を解消します。
最初のsort
(右側のもの) は入力リストをソートします。これは、隣接する等しい要素をサブリストgroup
にグループ化するためです。(ちなみに、これらのサブリストは空にならないことが保証されています --- そうでなければ、パターン マッチで空のリスト オプションを使用したり無視したりすることは安全ではありません。)head
次にmap f
は、これらのリスト (例: ["a", "a"]
) を関心のあるものに変換します: これらの要素が出現する回数と、これらの要素の単一の代表例 (例: (2, "a")
)。
ここでの慣用句は、パイプラインを使用しているということです。入力は関数に入り、その関数の出力は別の関数に入り、パイプラインの最後の関数が出力を生成し、それを独自の出力として提示するまで続きます。 . これは、各関数が 1 つの引数しかとらないためにのみ機能することに注意してください ( map
2 つの引数を取り、f
はそれらの引数の最初の引数なので、map f
1 つの引数を取ります)。
この結果、answer
引数が明示的に表示されなくても、 は関数です。ポイントフリースタイルです。
ポイントフリーでないスタイルでは、次のようになります。
answer xs = sort . map f . group . sort $ xs
where f xs @ (x:_) = (length xs, x)
また
answer xs = sort $ map f $ group $ sort xs
where f xs @ (x:_) = (length xs, x)
また
answer xs = sort (map f (group (sort xs)))
where f xs @ (x:_) = (length xs, x)
コードを明確にする場合は、ポイントフリー スタイルを使用することをお勧めします。
必要に応じて、演算子を使用して<<<
(Control.Arrow から、申し訳ありませんが) データフローの方向を表面的により明示的にすることができます。
import Data.List (sort, group)
import Control.Arrow ((<<<))
answer :: Eq a => [a] -> [(Int, a)]
answer = sort <<< map f <<< group <<< sort
where f xs @ (x:_) = (length xs, x)
一部の人々は、これは間違った方法であり、最初に「発生」する関数を左側に置きたいと考えています。これらの人々は、(Control.Arrowからも)使用できます。これは、引数が反転することを除いて>>>
、とまったく同じです。<<<
import Data.List (sort, group)
import Control.Arrow ((>>>))
answer :: Eq a => [a] -> [(Int, a)]
answer = sort >>> group >>> map f >>> sort
where f xs @ (x:_) = (length xs, x)