简体   繁体   English

输入可变Haskell堆的签名

[英]Type signatures for a mutable Haskell Heap

I want to make in Haskell a mutable array based heap (the basic kind found everywhere else). 我想在Haskell中创建一个基于可变数组的堆(在其他地方找到的基本类)。 There are some things I don't like about my initial approach, however: 但是,有些事情我不喜欢我最初的方法:

  • I use tuples to represent my heaps instead of a proper data type 我使用元组来表示我的堆而不是正确的数据类型
  • I don't know how to declare the types I am using (too many type variables around), relying on type inference (and copying examples from the Haskell Wiki) 我不知道如何声明我正在使用的类型(周围的类型变量太多),依赖于类型推断(以及从Haskell Wiki复制示例)
  • My heap isn't polymorphic 我的堆不是多态的
  • When using my heap in the f example function, I have to thread the n s around. f示例函数中使用我的堆时,我必须绕过n s。

What would be the best way to abstract my heap into a nice data type? 将我的堆抽象为一个漂亮的数据类型的最佳方法是什么? I feel this would solve most of my problems. 我觉得这可以解决我的大部分问题。

buildHeap max_n =
  do
    arr <- newArray (1, max_n) 0 :: ST s (STArray s Int Int)
    return (0, arr)
  -- My heap needs to know the array where the elements are stored
  -- and how many elements it has

f n =  --example use
  do
    (n1, arr) <- buildHeap n
    (n2, _) <- addHeap (n1, arr) 1
    (n3, _) <- addHeap (n2, arr) 2
    getElems arr
main = print $ runST (f 3)

You should definitely wrap the underlying representation in an abstract data type, and provide only smart constructors for building and taking apart your heap data structure. 您绝对应该将基础表示包装在抽象数据类型中,并且仅提供用于构建和拆分堆数据结构的智能构造函数。

Mutable structures tend to have simpler APIs than immutable ones (as they support fewer nice behaviors). 可变结构往往比不可变结构具有更简单的API(因为它们支持较少的好行为)。 To get a sense for what a reasonable API for a mutable container type looks like, including how to abstract the representation, perhaps look at the Judy package . 要了解可变容器类型的合理API是什么样的,包括如何抽象表示,也许请查看Judy包

In particular, 尤其是,

And the API: 和API:

new :: JE a => IO (JudyL a)  
  -- Allocate a new empty JudyL array.

null :: JudyL a -> IO Bool   
  -- O(1), null. Is the map empty?

size :: JudyL a -> IO Int       
  -- O(1), size. The number of elements in the map.

lookup :: JE a => Key -> JudyL a -> IO (Maybe a) 
  -- Lookup a value associated with a key in the JudyL array.

insert :: JE a => Key -> a -> JudyL a -> IO () 
  -- Insert a key and value pair into the JudyL array. Any existing key will be overwritten.

delete :: Key -> JudyL a -> IO ()  
  -- Delete the Index/Value pair from the JudyL array.

You'll need to support many of the same operations, with similar type signatures. 您需要支持许多相同的操作,具有类似的类型签名。

The actual, underlying representation of a JudyL is given by: JudyL的实际底层表示由下JudyL给出:

newtype JudyL a =
            JudyL { unJudyL :: MVar (ForeignPtr JudyL_) }

type JudyL_ = Ptr JudyLArray

data JudyLArray

Notice how we provide thread safety by locking the underlying resource (in this case, a C pointer to a data structure). 请注意我们如何通过锁定底层资源(在这种情况下,指向数据结构的C指针)来提供线程安全性。 Separately, the representation is abstract, and not visible to the user, keeping the API simple. 另外,表示是抽象的,并且对用户不可见,使API保持简单。

A general piece of advice for a beginner -- start with IOArrays rather than STArrays so you don't have to worry about higher-kinded types and the other tricks that come with ST. 一个初学者的一般建议 - 从IOArrays而不是STArrays开始,所以你不必担心更高级的类型和ST带来的其他技巧。 Then, after you've gotten something you're happy with, you can think about how to move it, if you desire, to ST. 然后,在你得到一些你满意的东西之后,如果你愿意,你可以考虑如何将它移动到ST。

Along with that, you should make your own ADT instead of tuples. 除此之外,你应该制作自己的ADT而不是元组。

data MutHeap a = MutHeap Int (IOArray Int a)

buildHeap max_n = do
  arr <- newArray_ (1, max_n) 
  return (MutHeap 0 arr)

etc. 等等

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM