新类型的未装箱向量挂在 basicUnsafeNew 中
Unboxed vector of newtype hangs in basicUnsafeNew
我试图在 space 中存储一个简单的三维点向量。为此,我正在 newtype
-ing 自定义 Point
并为其手动实施 Data.Vector.Unboxed.Vector
和 Data.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
代码需要 vector
和 linear
包。
为了方便起见,我将此代码推送为 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)
我试图在 space 中存储一个简单的三维点向量。为此,我正在 newtype
-ing 自定义 Point
并为其手动实施 Data.Vector.Unboxed.Vector
和 Data.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
代码需要 vector
和 linear
包。
为了方便起见,我将此代码推送为 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)