【问题标题】:Extracting elements from STArray (similar to unzipping)从 STArray 中提取元素(类似于解压缩)
【发布时间】:2012-11-19 15:01:02
【问题描述】:

我在 Haskell 中为编程竞赛实施基于粒子的流体模拟时遇到了一个小问题。我目前有一组粒子,它们在每个模拟步骤中都会被修改。每个粒子都是 2 个向量的元组:位置和速度(我自己的 Vec3D 模块)。在某些时候,我需要从我尝试这样做的粒子(有点像解压缩列表)中提取位置:

let xs = runSTArray $ do
    xs' <- newArray (min, max) (0.0,0.0,0.0) :: ST s (STArray s Int Vec3D)
    forM_ [min..max] $ \j -> do
        (x, v) <- readArray ps' j
        writeArray xs' j x
    return xs'
let displacements = doubleDensityRelaxation xs restDen k kNear t h

其中ps'doubleDensityRelaxation 属于类型

type Vec3D = (Double, Double, Double)
ps' :: ST s (STArray s Int (Vec3D, Vec3D))
doubleDensityRelaxation :: Array Int Vec3D -> Double -> Double -> Double -> Double -> Double -> Array Int Vec3D

所以xs 应该是xs :: Array Int Vec3D 类型。但是,我得到了

Simulator.hs:76:35:
No instance for (MArray (STArray s) (Vec3D, Vec3D) (ST s1))
  arising from a use of `readArray'
Possible fix:
  add an instance declaration for
  (MArray (STArray s) (Vec3D, Vec3D) (ST s1))
In a stmt of a 'do' block: (x, v) <- readArray ps' j
In the expression:
  do { (x, v) <- readArray ps' j;
       writeArray xs' j x }
In the second argument of `($)', namely
  `\ j
     -> do { (x, v) <- readArray ps' j;
             writeArray xs' j x }'

来自我不太了解的编译器,因为readArray 不应该返回整个数组;只有一个(Vec3D, Vec3D) 元素。

作为修复,我可以让doubleDensityRelaxation 直接使用ST s (STArray s Int Vec3D) 吗?

如果我像这样更改类型并删除let xs = runSTArray $ do 部分,我会得到

Couldn't match expected type `ST s0 (STArray s0 Int Vec3D)'
            with actual type `STArray s Int Vec3D'

但是如果我给它(ST s xs') 而不仅仅是xs' 它会抱怨数据构造函数ST 不在范围内。我的进口目前是

import Data.List
import Data.Array
import Data.Array.ST
import Control.Monad
import Control.Monad.ST
import Vec3D  

功能齐全:

step :: Array Int (Vec3D, Vec3D) -> Vec3D -> Double -> Double -> Double -> Double -> Double -> Array Int (Vec3D, Vec3D)
step ps g restDen k kNear t h = runSTArray $ do
    ps' <- thaw ps :: ST s (STArray s Int Particle)
    --GRAVITY
    forM_ [min..max] $ \i -> do
        (x, v) <- readArray ps' i
        writeArray ps' i (x, addGravity v g t)
    --TODO - VISCOSITY
    --MOVE
    xsOld <- newArray (min, max) (0.0,0.0,0.0) :: ST s(STArray s Int Vec3D)
    forM_ [min..max] $ \i -> do
        (x, v) <- readArray ps' i
        writeArray xsOld i x
        writeArray ps' i (x `add` (v `mulSc` t), v)
    --TODO - SPRINGS
    --DOUBLE DENSITY RELAXATION
    xs' <- newArray (min, max) (0.0,0.0,0.0) :: ST s (STArray s Int Vec3D)
    forM_ [min..max] $ \j -> do
        (x, v) <- readArray ps' j
        writeArray xs' j x
    let displacements = doubleDensityRelaxation (freeze xs') restDen k kNear t h
    ps <- newArray (min, max) ((0.0,0.0,0.0), (0.0,0.0,0.0)) :: ST s (STArray s Int (Vec3D, Vec3D))
    --TODO incomplete
    return ps
    where
        addGravity v g t = v `add` (g `mulSc` t)
        (min, max) = bounds ps

【问题讨论】:

  • 你能发布一个完整的例子吗?问题在于ps' 的类型(它应该是STArray s Int (Vec3D, Vec3D),没有ST s ...),但是如果不知道ps' 的来源,就很难就如何修复它给出好的建议。
  • @hammar - 我明白你的意思。如果我在一开始就把 ST 带走,它会给我这个: Simulator.hs:60:21: Couldn't match expected type 'Vec3D' with actual type 'Int'. Expected type: Array Vec3D Vec3D. Actual type: Array Int (Vec3D, Vec3D). In the first argument of 'thaw', namely 'ps'. In a stmt of a 'do' block: ps' &lt;- thaw ps :: STArray s Int Particle
  • 如果我将 freeze 调用从 let displacements = ... line 移到 xs'' &lt;- freeze xs',然后使用 xs'' 而不是 freeze xs' (hpaste),您更新的代码就会编译。
  • @hammar 我得到No instance for (Data.Array.Base.IArray b0 Vec3D)(类型变量b0 不明确)没有类型签名,并且获得正确的签名有点不平凡。
  • @LemonLord freeze :: (Ix i, MArray a e m, IArray b e) =&gt; a i e -&gt; m (b i e)。所以你的freeze xs'IArray b Vec3D =&gt; ST s (b Int Vec3D)。要获取实际的数组,您需要在 runSTArray 中运行 freeze

标签: arrays haskell unzip mutable st-monad


【解决方案1】:

基于 cmets 的社区 wiki 答案:

如果您将freeze 调用从let displacements = ... 行移到xs'' &lt;- freeze xs',然后使用xs'' 而不是freeze xs',则会编译更新的代码

这是因为freeze :: (Ix i, MArray a e m, IArray b e) =&gt; a i e -&gt; m (b i e)。所以freeze xs'IArray b Vec3D =&gt; ST s (b Int Vec3D)。要获取实际的数组,您需要在 runSTArray 内运行 freeze

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多