简体   繁体   English

newtype 的未装箱向量挂在 basicUnsafeNew 中

[英]Unboxed vector of newtype hangs in basicUnsafeNew

I'm trying to store a simple vector of three-dimensional points in space.我正在尝试在空间中存储一个简单的三维点向量。 To do this, I'm newtype -ing a custom Point and manually implement the Data.Vector.Unboxed.Vector and Data.Vector.Unboxed.Mutable instances for it.为此,我新建了一个自定义PointData.Vector.Unboxed.Vector newtype Data.Vector.Unboxed.Mutable实例。

However, for some reason, any attempt to use such a vector ends up in an infinite loop in basicUnsafeNew .但是,由于某种原因,任何使用此类向量的尝试都会在basicUnsafeNew中陷入无限循环。 The following program will hang:以下程序将挂起:

{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeFamilies #-}

import qualified Data.Vector.Generic as G
import qualified Data.Vector.Generic.Mutable as GM
import qualified Data.Vector.Unboxed as U
import qualified Data.Vector.Unboxed.Mutable as UM
import Debug.Trace (trace)
import Linear (V3 (..))

-- ct => "coordinate type"
newtype Point ct = Point
  { coordinates :: ct
  }
  deriving (Show, Eq)

makePoint :: a -> a -> a -> Point (Linear.V3 a)
makePoint x y z = Point (V3 x y z)

newtype instance UM.MVector s (Point ct) = MV_Point (UM.MVector s (Point ct))

newtype instance U.Vector (Point ct) = V_Point (U.Vector (Point ct))

instance (U.Unbox ct) => GM.MVector UM.MVector (Point ct) where
  {-# INLINE basicUnsafeNew #-}
  basicLength (MV_Point mv) = error "basicLength"
  basicUnsafeSlice i l (MV_Point mv) = error "basicUnsafeSlice"
  basicOverlaps (MV_Point mv) (MV_Point mv') = error "basicOverlaps"
  basicUnsafeNew l = trace "unsafe new" (MV_Point <$> GM.basicUnsafeNew l) -- <-- hangs!
  basicInitialize (MV_Point mv) = error "basicInitialize"
  basicUnsafeRead (MV_Point mv) i = error "basicUnsafeRead"
  basicUnsafeWrite (MV_Point mv) i x = error "basicUnsafeWrite"

instance (U.Unbox ct) => G.Vector U.Vector (Point ct) where
  basicUnsafeFreeze (MV_Point mv) = error "basicUnsafeFreeze"
  basicUnsafeThaw (V_Point v) = error "basicUnsafeThaw"
  basicLength (V_Point v) = error "basicLength"
  basicUnsafeSlice i l (V_Point v) = error "basicUnsafeSlice"
  basicUnsafeIndexM (V_Point v) i = error "basicUnsafeIndexM"

instance (U.Unbox ct) => U.Unbox (Point ct)

main :: IO ()
main = print $ U.length $ U.singleton $ makePoint (0.0 :: Double) 1.0 2.0

The code requires the vector and linear packages.该代码需要vectorlinear包。

I pushed this code as MWE with stack support here for convenience: https://github.com/jtprobst/vectortest为方便起见,我将此代码推送为 MWE,并在此处提供stack支持: https://github.com/jtprobst/vectortest

Simply call stack run and observe the endless traces of "unsafe new".只需调用stack run并观察“unsafe new”的无尽痕迹。

I'm running with stack --version Version 2.5.1, Git revision d6ab861544918185236cf826cb2028abb266d6d5 x86_64 hpack-0.33.0我正在使用stack --version Version 2.5.1, Git revision d6ab861544918185236cf826cb2028abb266d6d5 x86_64 hpack-0.33.0

Note that all methods except basicUnsafeNew on the vector default to error instead of doing anything useful.请注意,除了向量上的basicUnsafeNew之外的所有方法都默认为error ,而不是做任何有用的事情。 This is just to exclude the possibility of them interfering in any way.这只是为了排除他们以任何方式干扰的可能性。 It also hangs if I use the typical default implementations for these methods (for example as described in this answer on SO , point number 2).如果我对这些方法使用典型的默认实现,它也会挂起(例如,如关于 SO 的此答案中所述,第 2 点)。

Any hints as to what I'm doing wrong are highly appreciated.任何关于我做错了什么的提示都非常感谢。

Well, just unroll the newtype definition:好吧,只需展开 newtype 定义:

newtype instance UM.MVector s (Point ct)
     = MV_Point (UM.MVector s (Point ct))
     = MV_Point (MV_Point (UM.MVector s (Point ct)))
     = MV_Point (MV_Point (MV_Point (UM.MVector s (Point ct))))
     = MV_Point (MV_Point (MV_Point (MV_Point (UM.MVector s (Point ct)))))
     = MV_Point (MV_Point (MV_Point (MV_Point (MV_Point (UM.MVector s (Point ct))))))
     = MV_Point (MV_Point (MV_Point (MV_Point (MV_Point (MV_Point (UM.MVector s (Point ct)))))))
     = ...

This clearly isn't going anywhere.这显然不会去任何地方。

You need to define it in terms of something that is already defined, not in terms of the type you're just right now defining yourself, to avoid the circular reference.您需要根据已经定义的内容定义它,而不是根据您现在定义自己的类型来定义它,以避免循环引用。 The obvious candidate would be显而易见的候选人是

newtype instance UM.MVector s (Point ct) = MV_Point (UM.MVector s ct)

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

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