我想在一個簡單的新型別上使用未裝箱的向量,但我不清楚如何啟用它。到目前為止我所擁有的:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE TypeFamilies #-}
module UnboxedTest where
import Data.Vector.Unboxed
import Data.Word
newtype X = X Word64 deriving (Unbox)
我得到:
src/UnboxedTest.hs:11:32: error:
? No instance for (Data.Vector.Generic.Base.Vector Vector X)
arising from the 'deriving' clause of a data type declaration
Possible fix:
use a standalone 'deriving instance' declaration,
so you can specify the instance context yourself
? When deriving the instance for (Unbox X)
|
11 | newtype X = X Word64 deriving (Unbox)
如何將其放入未裝箱的向量中?
uj5u.com熱心網友回復:
如果有一個同構型別已經可以存盤在未裝箱的向量中,那就很簡單了。因為Point那是(Word64, Word64)。
您必須按照該檔案頁面的說明進行操作并撰寫:
{-# LANGUAGE TypeFamilies #-}
import Data.Vector.Unboxed
import Data.Vector.Unboxed.Mutable (MVector)
import qualified Data.Vector.Generic as G
import qualified Data.Vector.Generic.Mutable as GM
import Data.Word
data Point = Point Word64 Word64
newtype instance MVector s Point = MV_Point (MVector s (Word64,Word64))
newtype instance Vector Point = V_Point (Vector (Word64,Word64))
instance GM.MVector MVector Point where
{-# INLINE basicLength #-}
basicLength (MV_Point v) = GM.basicLength v
{-# INLINE basicUnsafeWrite #-}
basicUnsafeWrite (MV_Point v) i (Point x y) = GM.basicUnsafeWrite v i (x, y)
...
instance G.Vector Vector Point where
{-# INLINE basicLength #-}
basicLength (V_Point v) = G.basicLength v
{-# INLINE basicUnsafeIndexM #-}
basicUnsafeIndexM (V_Point v) i = do
(x, y) <- G.basicUnsafeIndexM v i
pure (Point x y)
...
instance Unbox Point
這些宣告指定如何將您的Point轉換為 a(Word64, Word64)以存盤在未裝箱的向量中。更明顯的是,如果您查看例如basicUnsafeWriteandbasicUnsafeIndexM函式,您可以看到實際上確實需要撰寫一些代碼來轉換Point和(Word64, Word64)回傳,這些并不是完全多余的。
uj5u.com熱心網友回復:
盡管 Haskell 的各種派生機制仍然無法生成與型別族相關的類的實體(就像Unboxed.Vector在本例中一樣),但始終有可能使用 Template Haskell 生成實體,它基本上可以做任何你可以手動做的事情。幸運的是,有人已經在包Unbox中撰寫了生成實體的宏:vector-th-unbox
{-# LANGUAGE TemplateHaskell, MultiParamTypeClasses, TypeFamilies, FlexibleInstances #-}
import Data.Vector.Unboxed.Deriving (derivingUnbox)
newtype X = X Word64
derivingUnbox "X"
[t| X -> Word64 |]
[| \(X w) -> w |]
[| X |]
實際上,由于這是一種新型別,我很想建議使用更簡單的宏:
import Data.Coerce
import Language.Haskell.TH
derivingNewtypeUnbox :: String -> TypeQ -> DecsQ
derivingNewtypeUnbox tfq tg = derivingUnbox tfq tg [|coerce|] [|coerce|]
然后它只是
derivingNewtypeUnbox "X" [t| X -> Word64 |]
uj5u.com熱心網友回復:
由于版本vector-0.13可以用于GeneralizedNewtypeDeriving派生Unbox,請參閱檔案
這是黑線鱈的例子:
>>> :set -XTypeFamilies -XStandaloneDeriving -XMultiParamTypeClasses -XGeneralizedNewtypeDeriving
>>>
>>> import qualified Data.Vector.Unboxed as U
>>> import qualified Data.Vector.Generic as G
>>> import qualified Data.Vector.Generic.Mutable as M
>>>
>>> newtype Foo = Foo Int
>>>
>>> newtype instance U.MVector s Foo = MV_Int (U.MVector s Int)
>>> newtype instance U.Vector Foo = V_Int (U.Vector Int)
>>> deriving instance M.MVector MVector Foo
>>> deriving instance G.Vector Vector Foo
>>> instance Unbox Foo
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/528501.html
標籤:哈斯克尔向量拆箱
