Haskell 就地多态快速排序中的数组类型参数

Haskell 就地多态快速排序中的数组类型参数,haskell,Haskell,我想实现一个多态快速排序。我想具体说明一下 IArray UArray a=>[a]->[a]中的类型a和sts(stus数组Int a)中的类型相同。我该怎么做 {-# LANGUAGE FlexibleContexts #-} module Quicksort where import Control.Monad.ST (ST) import Data.Array.ST (runSTUArray, newListArray, STUArray) import Data.Array.IArr

我想实现一个多态快速排序。我想具体说明一下
IArray UArray a=>[a]->[a]
中的类型a和
sts(stus数组Int a)
中的类型相同。我该怎么做

{-# LANGUAGE FlexibleContexts #-}
module Quicksort where

import Control.Monad.ST (ST)
import Data.Array.ST (runSTUArray, newListArray, STUArray)
import Data.Array.IArray (elems)
import Data.Array.Unboxed (UArray, IArray)

quicksort :: IArray UArray a => [a] -> [a]
quicksort l = elems $ runSTUArray $
  do newListArray (0, 9) l :: ST s (STUArray s Int a)

通过启用
ScopedTypeVariables
并在顶级类型签名中,您可以进入下一个错误:

quicksort :: forall a. IArray UArray a => [a] -> [a]
然后,您会发现您的
STUArray
不是
MArray
的一个实例,因为有一个用于任意
a
。如果将其设置为
Int
,它将编译


当然,明显没有这样一个实例的原因是,一个未绑定数组只能包含一个不可执行的值,这将是一个基本类型的值,一个详尽的列表,您可以在中查看。

您可以使用
Data.Constraint.Forall
使此操作适用于任何不可执行的对象。然而,由于该机制的工作方式,它可能不是最有效的。一种更烦人但可能更好的方法是编写一个类似于
MArray
的类,使用一个需要
s
参数的构造函数

{-# Language MultiParamTypeClasses, ScopedTypeVariables, ConstraintKinds,
  FlexibleInstances, FlexibleContexts, UndecidableInstances, TypeOperators #-}
module QS where

import Control.Monad.ST (ST, runST)
import Data.Constraint (Dict (..), (:-) (..))
import Data.Constraint.Forall (Forall, inst)
import Data.Array.ST (runSTUArray, newListArray, STUArray, MArray)
import Data.Array.IArray (elems)
import Data.Array.Unboxed (UArray, IArray)

type UnboxF a s = MArray (STUArray s) a (ST s)

class UnboxF a s => UnboxC a s
instance UnboxF a s => UnboxC a s

marrayDict :: Forall (UnboxC a) => Dict (UnboxC a s)
marrayDict = case inst :: Forall (UnboxC a) :- UnboxC a s of
               Sub x -> x

quicksort :: forall a. (IArray UArray a, Forall (UnboxC a)) => [a] -> [a]
quicksort l = elems $ runSTUArray
  ( case marrayDict :: Dict (UnboxC a s) of { Dict ->
      do
        newListArray (0,9) l
    } :: forall s. ST s (STUArray s Int a))

test :: [Char] -> [Char]
test = quicksort

当然,这可以通过额外的限制得到改善。导入
Data.Constraint for all
,定义
类型unbxf a s=MArray(stu数组s)a(ST s)
类unbxf a s=>unbxc a s
实例unbxf a s=>unbxc a s
,为all(unbxc a)添加约束
添加到函数中,并根据需要使用
inst
。@d我发现这个注释很难理解。具体地说,您指的是什么
inst
?有关更多详细信息,请参阅我的答案。