gpt4 book ai didi

haskell - 是否可以通过 GHC 的通用派生来派生 Data.Vector.Unbox?

转载 作者:行者123 更新时间:2023-12-01 13:14:30 26 4
gpt4 key购买 nike

可以导出 Storable通过 GHC 的通用推导机制:http://hackage.haskell.org/package/derive-storable (和 https://hackage.haskell.org/package/derive-storable-plugin 用于性能)。我能找到的唯一用于推导的库 Data.Vector.Unbox但是,使用模板 Haskell:http://hackage.haskell.org/package/vector-th-unbox .它还需要用户编写一些代码;这不是完全自动的。

我的问题是,像 deriving-storable 这样的图书馆可以吗?也存在于 Unbox ,或者这是不可能的,因为 Unbox 的某些基本方式不同于 Storable ?如果是后者,是否意味着也无法创建允许自动派生 Unbox 的库?对于任何 Storable类型,因为我找不到这样的库。

我问是因为理想情况下我想避免使用模板 Haskell 和使用 vector-th-unbox 所需的手动注释。 .

最佳答案

假设我们有一些 Generic_在我们自己的类型和碰巧有 Unbox 的一些统一表示之间转换的类实例(对于 MVector 变体,这相当于 VectorUnboxed 实例):

class Generic_ a where
type Rep_ (a :: Type) :: Type
to_ :: a -> Rep_ a
from_ :: Rep_ a -> a

然后我们可以使用它来获得 MVector 方法的通用实现。/ Vector :
-- (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_例如,您可以将其替换为 MyTypeYourType .
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_本质上是 Generic来自 GHC.Generics .然而,由 GHC 导出的统一表示不是元组 (,)但就有些特殊的类型构造函数( :+::*:M1 等)而言,缺少 Unbox实例。
  • 这样的Unbox可以添加实例以使用 Generic直接
  • generics-eotGeneric 的变体依赖可以直接替代 Generic_ 的元组这里。

  • 其次, MVectorVector有不少方法。为了避免将它们全部列出,人们可能希望利用 DerivingVia (或 GeneralizedNewtypeDeriving ),但是它们不适用,因为有几个多态一元方法可以防止强制转换(例如, basicUnsafeNew )。目前,我能想到的最简单的抽象方法是 CPP 宏。事实上,vector 包在内部使用了该技术,并且它可能以某种方式可重用。我相信正确解决这些问题需要对 Vector/MVector 架构进行深入的重新设计。

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

    关于haskell - 是否可以通过 GHC 的通用派生来派生 Data.Vector.Unbox?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56790032/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com