当前位置: 首页 > 知识库问答 >
问题:

Haskell中现有的大小惰性向量类型

钮长恨
2023-03-14

我希望能够使用O(1)摊销寻址与一个矢量类型,懒散地增长,根据要求的指数。

这可以通过使用mvector(PrimState m)a:与primref m[a]进行配对来保持剩余部分,并使用用于分期O(1)访问的标准加倍算法来实现:

{-# LANGUAGE ExistentialQuantification #-}
module LazyVec where

import Control.Monad.Primitive
import Data.PrimRef
import Data.Vector.Mutable (MVector)
import qualified Data.Vector.Mutable as M
import Data.Vector (fromList, thaw)
import Control.Monad (forM_)

data LazyVec m a = PrimMonad m => LazyVec (MVector (PrimState m) a) (PrimRef m [a])

-- prime the LazyVec with the first n elements
lazyFromListN :: PrimMonad m => Int -> [a] -> m (LazyVec m a)
lazyFromListN n xs = do
  let (as,bs) = splitAt n xs
  mvec <- thaw $ fromList as
  mref <- newPrimRef bs
  return $ LazyVec mvec mref

-- look up the i'th element
lazyIndex :: PrimMonad m => Int -> LazyVec m a -> m a
lazyIndex i lv@(LazyVec mvec mref) | i < 0     = error "negative index"
                                   | i < n     = M.read mvec i
                                   | otherwise = do
    xs <- readPrimRef mref
    if null xs
      then error "index out of range"
      else do
        -- expand the mvec by some power of 2
        -- so that it includes the i'th index
        -- or ends
        let n' = n * 2 ^ ( 1 +  floor (logBase 2 (toEnum (i `div` n))))
        let growth = n' - n
        let (as, bs) = splitAt growth xs
        M.grow mvec $ if null bs then length as else growth
        forM_ (zip [n,n+1..] as) . uncurry $ M.write mvec
        writePrimRef mref bs
        lazyIndex i lv
  where n = M.length mvec

我可以只使用我的代码--但我更愿意重用别人的(比如,我还没有测试过我的代码)。

在某些包中是否存在具有这些语义的向量类型(从一个可能无限的列表中懒散地创建、O(1)分期访问)?

共有1个答案

长孙嘉容
2023-03-14

正如Jake McArthur在评论中指出的:“如果它只是一个函数,那么我建议只使用现有的备忘录包之一,比如MemoTrie或data-memocombinators。它们应该会让它变得容易。”

 类似资料:
  • 简介 在上一个部分我们对比了Twisted与 Erlang,并将注意力集中在它们共有的一些思想上.结果表明使用Erlang也是非常简便的,因为异步I/O和响应式编程是Erlang运行时和进程模型的关键元素. 今天我们想走得更远一点,去看一看 Haskell —— 另一种功能性语言,然而与Erlang有很大不同(当然与Python也不同).这里面没有太多的平行概念,但我们仍然会发现藏在下面的异步I/

  • 可以以与斐波那契数列类似的方式生成如下, 如何定义阶乘级数。 使现代化 令人尴尬的是,在添加这个问题之前,我已经试过了, 事实上,尾部的数字并不是连续的值。

  • 我正在为一个系统建模,该系统有一个创建资源的操作和其他消耗该资源的操作。然而,一个给定的资源只能被消耗一次——有没有一种方法可以保证在编译时这样做? 具体来说,假设第一个操作烘焙蛋糕,还有另外两个操作,一个用于“选择吃”蛋糕,另一个用于“选择吃蛋糕”,我只能做其中一个。 通过在我们使用蛋糕后在蛋糕上设置一个标志,很容易在运行时强制执行不保留已经吃过的蛋糕(反之亦然)的限制。但是有没有办法在编译时强

  • 问题内容: 遵循“只有一种明显的方法”,如何在Numpy中获得向量(一维数组)的大小? 上面的方法有效,但是我 不敢相信 自己必须指定这样一个琐碎的核心功能。 问题答案: 您需要的功能是。(我认为它应该作为数组的属性存在于基本numpy中-说-但很好)。 您还可以根据需要输入可选的n阶范数。假设您想要1范数: 等等。

  • 我正在对大小为50,000个元素的两个向量执行基于元素的操作,并且有不满意的性能问题(几秒钟)。是否存在明显的性能问题,例如使用不同的数据结构?

  • 这些到底有什么区别呢?我想我理解存在类型是如何工作的,它们就像OO中的基类没有向下强制转换的方法一样。通用类型有何不同?