You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在原地多态快速排序中指定STUArray与IArray的类型参数a一致

实现多态快速排序并保证类型一致性

没问题,要实现这个多态快速排序并保证IArray UArray a和ST s (STUArray s Int a)中的a是同一类型,核心是在函数签名中用同一个类型变量绑定所有场景的a,并添加必要的约束来满足数组操作的要求。下面是具体实现方案:

1. 导入必要模块

首先需要导入Haskell数组和ST monad相关的核心模块:

import Data.Array.IArray (IArray, UArray, listArray, elems)
import Data.Array.ST (STUArray, runSTUArray, MArray, newArray, readArray, writeArray)
import Control.Monad.ST (ST)
import Control.Monad (forM_)
import Foreign.Storable (Storable) -- 简化约束时需要导入

2. 实现ST上下文内的原地快速排序

先写一个在ST上下文里操作STUArray的原地快排函数,这里的a和后续所有场景的类型保持一致:

-- 对STUArray进行原地快速排序
quickSortST :: (Ord a, MArray STUArray a (ST s)) => STUArray s Int a -> Int -> Int -> ST s ()
quickSortST arr low high
  | low >= high = return ()
  | otherwise = do
      pivot <- readArray arr high
      pivotIdx <- partition arr low high pivot 0
      quickSortST arr low (pivotIdx - 1)
      quickSortST arr (pivotIdx + 1) high
  where
    -- 分区函数:将小于等于pivot的元素移到左侧,返回pivot最终位置
    partition arr l h p i
      | l >= h = do
          -- 将pivot放到正确位置
          writeArray arr h =<< readArray arr (low + i)
          writeArray arr (low + i) p
          return (low + i)
      | otherwise = do
          val <- readArray arr l
          if val <= p
            then do
              -- 交换当前元素到左侧分区
              writeArray arr l =<< readArray arr (low + i)
              writeArray arr (low + i) val
              partition arr (l + 1) h p (i + 1)
            else partition arr (l + 1) h p i

3. 对外暴露的多态快排函数

这里定义对外的函数,通过同一个类型变量a绑定所有场景,并添加必要约束:

-- 多态快速排序:列表输入 -> 列表输出
polymorphicQuickSort :: (Ord a, IArray UArray a, MArray STUArray a (ST s)) => [a] -> [a]
polymorphicQuickSort [] = []
polymorphicQuickSort xs = elems $ runSTUArray $ do
  let n = length xs
      arrBounds = (0, n - 1)
  -- 创建可变数组并初始化
  arr <- newArray arrBounds undefined
  forM_ (zip [0..] xs) $ \(idx, val) -> writeArray arr idx val
  -- 执行原地快排
  quickSortST arr 0 (n - 1)
  return arr

简化约束(可选)

因为UArray和STUArray的元素类型都要求实现Storable类型类,而IArray UArray a和MArray STUArray a (ST s)这两个约束其实都隐含了Storable a,所以我们可以把约束简化成更简洁的形式:

polymorphicQuickSort :: (Ord a, Storable a) => [a] -> [a]

这样写法更简洁,且同样能保证a在所有场景下是同一类型。

4. 使用示例

测试一下这个函数,比如对整数列表排序:

main :: IO ()
main = print $ polymorphicQuickSort [3,1,4,1,5,9,2,6]
-- 输出:[1,1,2,3,4,5,6,9]

核心原理说明

  • 类型一致性保证:函数签名中所有出现的a都是同一个类型变量,所以列表中的a、UArray中的a、STUArray中的a必然是同一类型。
  • 约束作用:
    • Ord a:保证元素可以比较大小,满足排序的基本要求;
    • IArray UArray a:保证a可以作为不可变UArray的元素,支持列表和数组的转换;
    • MArray STUArray a (ST s):保证a可以作为可变STUArray的元素,支持ST上下文里的原地修改操作。

内容的提问来源于stack exchange,提问作者neo2500

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:56:46