使用 Struct 库的快速强制指针(静态、拆箱等)

Fast impertive pointers (static, unboxing, etc.) with Struct library

我有兴趣为在 Haskell 中实现命令式语言的项目使用更有效的指针。已经有 library for that: Struct. There is a blog post on it and brief documentation.

问题是 linkcut trees 只有一个相当复杂的例子。对于像我这样不每天使用 Haskell 的人来说,与少量文档化代码、模板 haskell 等作斗争是相当累人的

我需要一个更简单的示例来开始,按照表达这两种数据类型之一的方式:

import Data.IORef

data DLL a = DLL a (Maybe (IORef (DLL a))) (Maybe (IORef (DLL a)))

data DLLINT = DLLINT Int (Maybe (IORef DLLINT)) (Maybe (IORef DLLINT))

对于精通 Haskell/GHC 的人来说,这应该只是几行简单的代码。

如何使用 Struct 库表达上述数据类型之一?

我设法让你的 DLL 类型与 Structs 一起工作,如下所示:

{-# LANGUAGE TemplateHaskell, RoleAnnotations #-}
module DubLiList where

import Control.Monad.Primitive
import Data.Struct.TH
import Data.Struct
import Data.Struct.Internal


makeStruct [d|
  data DLL a s = DLL
    { prev :: !(DLL a s)
    , value :: a
    , next :: !(DLL a s)
    }
  |]

new :: (PrimMonad m) => a -> m (DLL a (PrimState m))
new x = st $ newDLL Nil x Nil

insert :: (PrimMonad m) => a -> DLL a (PrimState m) -> m (DLL a (PrimState m))
insert x this = st $ do
    prev' <- get prev this
    new <- newDLL prev' x this
    set prev this new
    set next prev' new
    return new

delete :: (PrimMonad m) => DLL a (PrimState m) -> m ()
delete this = st $ do
    prev' <- get prev this
    next' <- get next this
    set next prev' next'
    set prev next' prev'

toList :: (PrimMonad m) => DLL a (PrimState m) -> m [a]
toList this = st $ do
    if isNil this then return [] else do
        x <- getField value this
        that <- get next this
        (x:) <$> toList that

这是一个使用它的例子:

main :: IO ()
main = do
    dll <- new "foo"           -- [foo]
    dll' <- insert "bar" dll   -- [bar, foo]
    insert "baz" dll           -- [bar, baz, foo]

    xs <- toList dll'
    print xs