IO Compare 関数でリストをソートするにはどうすればよいですか?
sortWith :: [String] -> (String -> String -> IO Ordering) -> IO [String]
Sortby は期待(a->a->Ordering)
していますが、対処方法がわかりません。私は自分でクイックソートを実装するのが面倒です。
簡単な方法はないのではないかと心配しています。持ち上げることができれば
sortBy :: Ord a => (a -> a -> Ordering) -> [a] -> [a]
に
sortByM :: (Ord a, Monad m) => (a -> a -> m Ordering) -> [a] -> m [a]
の実装で比較の順序を確認できsortBy
、参照透過性に違反しています。
xxxM
一般に、からへは容易に移行できxxx
ますが、その逆には移行できません。
可能なオプション:
unsafePerformIO
ハックとして使うキーによる並べ替えに切り替えて、シュワルツ変換を使用する
sortOnM :: (Monad m, Ord k) => (a -> m k) -> [a] -> m [a]
sortOnM f xs = liftM (map fst . sortBy (comparing snd)) $
mapM (\x -> liftM (x,) (f x)) xs
あ、これやった事ある!モナドコンパレータを使用したマージソート:
type MComparator m a = a -> a -> m Ordering
sortByM :: (Monad m, Functor m) => MComparator m a -> [a] -> m [a]
sortByM cmp [] = return []
sortByM cmp [x] = return [x]
sortByM cmp xs = do
let (ys, zs) = partition xs
ys' <- sortByM cmp ys
zs' <- sortByM cmp zs
merge ys' zs'
where merge [] bs = return bs
merge as [] = return as
merge (a:as) (b:bs) = do
comparison <- cmp a b
case comparison of
LT -> (a:) <$> merge as (b:bs)
_ -> (b:) <$> merge (a:as) bs
partition xs = splitAt (length xs `quot` 2) xs
私のブログ投稿から: http://unknownparallel.wordpress.com/2012/07/03/using-monadic-effects-to-reverse-a-merge-sort/
このsortBy
関数は、GHC のアルゴリズムとしてマージ ソートを使用しますが、Haskell 98 レポートでは、挿入ソートを使用する必要があると規定されています。
簡単にするために、コンパイラがないためコードをテストできないため、ここで挿入ソートを実装します。
import Data.Foldable (foldrM)
insertByM :: (a -> a -> IO Ordering) -> a -> [a] -> IO [a]
insertByM _ x [] = return [x]
insertByM cmp x ys@(y:ys') = do
p <- cmp x y
case p of
GT -> do
rest <- insertByM cmp x ys'
return $ y : rest
_ -> return $ x : ys
sortByM :: (a -> a -> IO Ordering) -> [a] -> IO [a]
sortByM cmp = foldrM (insertByM cmp) []
私が言ったように、私はこのコードをテストしていませんが、動作する可能性があります/動作するはずです.
怠惰はプログラマーの 3 つの美徳の 1 つだと言ったのはラリー ウォールでしたか?
タイプ (a -> a -> b) の関数をタイプ (a -> a -> cb) の関数に変換したいようです。それをHoogleにプラグインしましょう。ここで、IO がモナドであることがわかっている場合は、liftM2 で 10 番目のマッチ ダウンについて確認できます。(liftM2 sortBy) のタイプを確認してください。それでよろしいですか?