新类型的未装箱向量挂在 basicUnsafeNew 中

Unboxed vector of newtype hangs in basicUnsafeNew

我试图在 space 中存储一个简单的三维点向量。为此,我正在 newtype-ing 自定义 Point 并为其手动实施 Data.Vector.Unboxed.VectorData.Vector.Unboxed.Mutable 实例。

但是,由于某种原因,任何使用此类向量的尝试都会在 basicUnsafeNew 中陷入无限循环。以下程序将挂起:

{-# 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

代码需要 vectorlinear 包。

为了方便起见,我将此代码推送为 MWE,并在此处提供 stack 支持:https://github.com/jtprobst/vectortest

只需调用 stack run 并观察“不安全新”的无尽痕迹。

我是 运行 stack --version 版本 2.5.1,Git 修订版 d6ab861544918185236cf826cb2028abb266d6d5 x86_64 hpack-0.33.0

请注意,向量上除 basicUnsafeNew 之外的所有方法都默认为 error 而不是做任何有用的事情。这只是为了排除他们以任何方式进行干预的可能性。如果我对这些方法使用典型的默认实现(例如 this answer on SO,第 2 点中所述),它也会挂起。

非常感谢任何关于我做错了什么的提示。

好吧,展开新类型定义:

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)))))))
     = ...

这显然不会有任何进展。

您需要根据 已经定义的内容来定义它,而不是根据您现在定义自己的类型来定义它,以避免循环引用。明显的候选人是

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