是否可以通过 GHC 的通用推导来推导 Data.Vector.Unbox?
Would it be possible to derive Data.Vector.Unbox via GHC's generic deriving?
可以通过 GHC 的通用派生机制派生 Storable
:http://hackage.haskell.org/package/derive-storable (and https://hackage.haskell.org/package/derive-storable-plugin for performance). The only library I can find for deriving Data.Vector.Unbox
, however, uses template Haskell: http://hackage.haskell.org/package/vector-th-unbox。它还需要用户编写一些代码;它不是完全自动的。
我的问题是,像 deriving-storable
这样的库是否也存在于 Unbox
,或者由于 Unbox
与 [=11= 的某些基本方式不同,这是不可能的]?如果是后者,这是否意味着也无法创建一个允许为任何 Storable
类型自动派生 Unbox
的库,因为我找不到这样的库。
我问是因为理想情况下我想避免模板 Haskell 和使用 vector-th-unbox
所需的手动注释。
假设我们有一些 Generic_
class 可以在我们自己的类型和一些统一表示之间进行转换,这些表示恰好有一个 Unbox
实例(相当于 MVector
和 Vector
个 Unboxed
变体的实例):
class Generic_ a where
type Rep_ (a :: Type) :: Type
to_ :: a -> Rep_ a
from_ :: Rep_ a -> a
方法的通用实现
-- (auxiliary definitions of CMV and uncoercemv at the end of this block)
-- vector imports (see gist at the end for a compilable sample)
import qualified Data.Vector.Unboxed as U
import qualified Data.Vector.Unboxed.Mutable as UM
import Data.Vector.Generic.Mutable.Base (MVector(..))
-- MVector
gbasicLength :: forall a s. CMV s a => UM.MVector s a -> Int
gbasicLength = basicLength @UM.MVector @(Rep_ a) @s . coerce
gbasicUnsafeSlice :: forall a s. CMV s a => Int -> Int -> UM.MVector s a -> UM.MVector s a
gbasicUnsafeSlice i j = uncoercemv . basicUnsafeSlice @UM.MVector @(Rep_ a) @s i j . coerce
-- etc.
-- idem Vector
-- This constraints holds when the UM.MVector data instance of a is
-- representationally equivalent to the data instance of its generic
-- representation (Rep_ a).
type CMV s a = (Coercible (UM.MVector s a) (UM.MVector s (Rep_ a)), MVector UM.MVector (Rep_ a))
-- Sadly coerce doesn't seem to want to solve this correctly so we use
-- unsafeCoerce as a workaround.
uncoercemv :: CMV s a => UM.MVector s (Rep_ a) -> UM.MVector s a
uncoercemv = unsafeCoerce
现在如果我们有一些通用类型
data MyType = MyCons Int Bool ()
我们可以定义一个与元组同构的泛型实例
instance Generic_ MyType where
type Rep_ MyType = (Int, Bool, ())
to_ (MyCons a b c) = (a, b, c)
from_ (a, b, c) = MyCons a b c
从那里,有一个完全通用的方法来获取它的 Unbox
实例,如果你有 YourType
而不是它自己的 Generic_
实例,你可以从字面上看这个将 MyType
替换为 YourType
.
newtype instance UM.MVector s MyType
= MVMyType { unMVMyType :: UM.MVector s (Rep_ MyType) }
instance MVector UM.MVector MyType where
basicLength = gbasicLength
basicUnsafeSlice = gbasicUnsafeSlice
-- etc.
-- idem (Vector U.Vector MyType)
-- MVector U.Vector & Vector UM.MVector = Unbox
instance Unbox MyType
理论上,所有这些样板文件都可以通过内部语言功能实现自动化(与 TemplateHaskell 或 CPP 相反)。但在目前的情况下,存在各种问题。
首先,Generic_
本质上是 GHC.Generics
的 Generic
。但是,由 GHC 派生的统一表示不是根据元组 (,)
,而是根据某种 ad-hoc 类型构造函数(:+:
、:*:
、M1
, 等), 缺少 Unbox
个实例。
- 可以添加这样的
Unbox
个实例以直接使用 Generic
- generics-eot 有一个
Generic
的变体,它依赖于可以直接替代 Generic_
的元组。
其次,MVector
和Vector
有很多方法。为了避免必须全部列出它们,人们可能希望利用 DerivingVia
(或 GeneralizedNewtypeDeriving
),但是它们不适用,因为有几个多态 monadic 方法可以防止强制转换(例如,basicUnsafeNew
).目前,我能想到的最简单的抽象方法是 CPP 宏。事实上,vector 包在内部使用了该技术,并且它可能以某种方式可重用。我认为正确解决这些问题需要对 Vector/MVector 架构进行深度重新设计。
要点(不完整,但可编译):https://gist.github.com/Lysxia/c7bdcbba548ee019bf6b3f1e388bd660
可以通过 GHC 的通用派生机制派生 Storable
:http://hackage.haskell.org/package/derive-storable (and https://hackage.haskell.org/package/derive-storable-plugin for performance). The only library I can find for deriving Data.Vector.Unbox
, however, uses template Haskell: http://hackage.haskell.org/package/vector-th-unbox。它还需要用户编写一些代码;它不是完全自动的。
我的问题是,像 deriving-storable
这样的库是否也存在于 Unbox
,或者由于 Unbox
与 [=11= 的某些基本方式不同,这是不可能的]?如果是后者,这是否意味着也无法创建一个允许为任何 Storable
类型自动派生 Unbox
的库,因为我找不到这样的库。
我问是因为理想情况下我想避免模板 Haskell 和使用 vector-th-unbox
所需的手动注释。
假设我们有一些 Generic_
class 可以在我们自己的类型和一些统一表示之间进行转换,这些表示恰好有一个 Unbox
实例(相当于 MVector
和 Vector
个 Unboxed
变体的实例):
class Generic_ a where
type Rep_ (a :: Type) :: Type
to_ :: a -> Rep_ a
from_ :: Rep_ a -> a
方法的通用实现
-- (auxiliary definitions of CMV and uncoercemv at the end of this block)
-- vector imports (see gist at the end for a compilable sample)
import qualified Data.Vector.Unboxed as U
import qualified Data.Vector.Unboxed.Mutable as UM
import Data.Vector.Generic.Mutable.Base (MVector(..))
-- MVector
gbasicLength :: forall a s. CMV s a => UM.MVector s a -> Int
gbasicLength = basicLength @UM.MVector @(Rep_ a) @s . coerce
gbasicUnsafeSlice :: forall a s. CMV s a => Int -> Int -> UM.MVector s a -> UM.MVector s a
gbasicUnsafeSlice i j = uncoercemv . basicUnsafeSlice @UM.MVector @(Rep_ a) @s i j . coerce
-- etc.
-- idem Vector
-- This constraints holds when the UM.MVector data instance of a is
-- representationally equivalent to the data instance of its generic
-- representation (Rep_ a).
type CMV s a = (Coercible (UM.MVector s a) (UM.MVector s (Rep_ a)), MVector UM.MVector (Rep_ a))
-- Sadly coerce doesn't seem to want to solve this correctly so we use
-- unsafeCoerce as a workaround.
uncoercemv :: CMV s a => UM.MVector s (Rep_ a) -> UM.MVector s a
uncoercemv = unsafeCoerce
现在如果我们有一些通用类型
data MyType = MyCons Int Bool ()
我们可以定义一个与元组同构的泛型实例
instance Generic_ MyType where
type Rep_ MyType = (Int, Bool, ())
to_ (MyCons a b c) = (a, b, c)
from_ (a, b, c) = MyCons a b c
从那里,有一个完全通用的方法来获取它的 Unbox
实例,如果你有 YourType
而不是它自己的 Generic_
实例,你可以从字面上看这个将 MyType
替换为 YourType
.
newtype instance UM.MVector s MyType
= MVMyType { unMVMyType :: UM.MVector s (Rep_ MyType) }
instance MVector UM.MVector MyType where
basicLength = gbasicLength
basicUnsafeSlice = gbasicUnsafeSlice
-- etc.
-- idem (Vector U.Vector MyType)
-- MVector U.Vector & Vector UM.MVector = Unbox
instance Unbox MyType
理论上,所有这些样板文件都可以通过内部语言功能实现自动化(与 TemplateHaskell 或 CPP 相反)。但在目前的情况下,存在各种问题。
首先,Generic_
本质上是 GHC.Generics
的 Generic
。但是,由 GHC 派生的统一表示不是根据元组 (,)
,而是根据某种 ad-hoc 类型构造函数(:+:
、:*:
、M1
, 等), 缺少 Unbox
个实例。
- 可以添加这样的
Unbox
个实例以直接使用Generic
- generics-eot 有一个
Generic
的变体,它依赖于可以直接替代Generic_
的元组。
其次,MVector
和Vector
有很多方法。为了避免必须全部列出它们,人们可能希望利用 DerivingVia
(或 GeneralizedNewtypeDeriving
),但是它们不适用,因为有几个多态 monadic 方法可以防止强制转换(例如,basicUnsafeNew
).目前,我能想到的最简单的抽象方法是 CPP 宏。事实上,vector 包在内部使用了该技术,并且它可能以某种方式可重用。我认为正确解决这些问题需要对 Vector/MVector 架构进行深度重新设计。
要点(不完整,但可编译):https://gist.github.com/Lysxia/c7bdcbba548ee019bf6b3f1e388bd660