Sorting Haskell——具有不纯函数的排序列表
如何使用IO比较功能对列表进行排序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场比
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