首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否可以通过GHC的泛型派生导出Data.Vector.Unbox?

是否可以通过GHC的泛型派生导出Data.Vector.Unbox?
EN

Stack Overflow用户
提问于 2019-06-27 11:28:06
回答 1查看 327关注 0票数 3

可以通过GHC的通用派生机制:Storable (以及性能方面的https://hackage.haskell.org/package/derive-storable-plugin )来派生https://hackage.haskell.org/package/derive-storable-plugin。然而,我唯一能找到的派生Data.Vector.Unbox的库是使用模板Haskell:http://hackage.haskell.org/package/vector-th-unbox。它还要求用户编写一些代码;它不是完全自动的。

我的问题是,像deriving-storable这样的库是否也存在于Unbox中,还是由于UnboxStorable的一些基本区别而不可能这样做?如果是后者,这是否意味着也不可能创建允许为任何Unbox类型自动派生Storable的库,因为我找不到这样的库。

我之所以这样问,是因为理想情况下,我希望避免模板Haskell和使用vector-th-unbox所必需的手动注释。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-27 15:05:10

假设我们有一些Generic_类要在我们自己的类型之间进行转换,而有些统一的表示正好有一个Unbox实例(对于Unboxed变体来说,这相当于MVectorVector实例):

代码语言:javascript
复制
class Generic_ a where
  type Rep_ (a :: Type) :: Type
  to_ :: a -> Rep_ a
  from_ :: Rep_ a -> a

然后,我们可以使用它来获得MVector/Vector方法的泛型实现。

代码语言:javascript
复制
-- (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

如果我们有一些通用类型

代码语言:javascript
复制
data MyType = MyCons Int Bool ()

我们可以定义一个泛型实例,并将其同构为元组。

代码语言:javascript
复制
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

代码语言:javascript
复制
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.GenericsGeneric。然而,由GHC派生的统一表示不是以元组(,)为基础的,而是以一些特殊类型的构造函数(:+::*:M1等)来表示的,这些构造函数缺少Unbox实例。

  • 可以添加这样的Unbox实例以直接使用Generic
  • 泛型-eot有一个Generic的变体,它依赖于元组,在这里可以直接替代Generic_

其次,MVectorVector有很多方法。为了避免将它们全部列出,人们可能会期望利用DerivingVia (或GeneralizedNewtypeDeriving),但是它们并不适用,因为有几个多态的一元方法可以防止强制(例如,basicUnsafeNew)。目前,我能想到的最简单的抽象方法是CPP宏。实际上,向量包在内部使用了这种技术,而且它可能会在某种程度上被重用。我认为,正确地解决这些问题需要对向量/矢量架构进行深入的重新设计。

Gist (不完整,但可编译):https://gist.github.com/Lysxia/c7bdcbba548ee019bf6b3f1e388bd660

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56790032

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档