Sorting Haskell——具有不纯函数的排序列表

Sorting Haskell——具有不纯函数的排序列表,sorting,haskell,io,Sorting,Haskell,Io,如何使用IO比较功能对列表进行排序 sortWith :: [String] -> (String -> String -> IO Ordering) -> IO [String] Sortby期望(a->a->订购),我不知道该怎么处理。我懒得自己实现快速排序。是拉里·沃尔说的懒惰是程序员的三大美德之一吗 似乎您想要将(a->a->b)类型的函数转换为(a->a->cb)类型的函数。让我们把它插进电脑。现在,如果你知道IO是一个单子,你将在liftM2中看到第10场比

如何使用IO比较功能对列表进行排序

sortWith :: [String] -> (String -> String -> IO Ordering) -> IO [String]

Sortby期望
(a->a->订购)
,我不知道该怎么处理。我懒得自己实现快速排序。

是拉里·沃尔说的懒惰是程序员的三大美德之一吗


似乎您想要将(a->a->b)类型的函数转换为(a->a->cb)类型的函数。让我们把它插进电脑。现在,如果你知道IO是一个单子,你将在liftM2中看到第10场比赛。检查类型(liftM2 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) []
导入数据。可折叠(foldrM)
insertByM::(a->a->IO排序)->a->[a]->IO[a]
insertByM x[]=返回[x]
insertByM cmp x ys@(y:ys')=do
p do

休息恐怕没有简单的方法。如果可能的话

sortBy :: Ord a => (a -> a -> Ordering) -> [a] -> [a]

您可以在
sortBy
的实现中看到比较的顺序,这违反了引用透明性

一般来说,从
xxxM
xxx
很容易,但不是相反

可能的选择:

  • 实现一种一元排序方法
  • 使用包含插入排序的库(如dflemstr的答案)
  • 使用
    unsafePerformIO
    作为攻击
  • 切换到按键排序并使用


    • 哦,我以前做过这个!使用一元比较器合并排序:

      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
      
      类型MComparator m a=a->a->m排序
      sortByM::(单子m,函子m)=>MComparator MA->[a]->m[a]
      sortByM cmp[]=返回[]
      sortByM cmp[x]=返回[x]
      sortByM cmp xs=do
      设(ys,zs)=分区xs
      
      Y'布尔的
      Bool
      是什么意思
      sortBy
      的类型为
      (a->a->Ordering)->[a]->[a]
      ,它使用一个函数返回
      排序,而不是
      Bool
      。这不是正确的答案。您应该注意到,比较函数(第二个参数)也在IO monad中。在Haskell Report 2010中,它不再要求使用插入排序。它只需要使用一个。GHC正在使用。你能详细说明一下为什么
      sortByM
      违反了引用透明度吗?
      sortByM
      没有违反它。将
      sortBy
      提升到
      sortByM
      的潜在功能不起作用。两个排序函数
      sortBy1,sortBy2::Ord a=>(a->a->Ordering)->[a]->[a]
      应该可以完全互换,即使它们以不同的顺序执行比较。如果让
      fij=print(i,j)>>返回(比较ij)
      lift sortBy1 f
      可能会打印与
      lift sortBy2 f
      不同的序列。
      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