自动派生 Data.Vector.Unbox 以及关联的类型同义词

2023-12-22

我有一个数据类型

newtype Zq q = Zq (IntType q)

其中“q”将是该类的一个实例

class Foo a where
   type IntType a

'IntType' 只是与 'q' 关联的底层表示(即 Int、Integral 等)。

我想让 Zq 成为一个实例数据.矢量.拆箱 http://hackage.haskell.org/packages/archive/vector/0.9.1/doc/html/Data-Vector-Unboxed.html。我们目前正在使用大约 50 行简单代码手动派生 Unbox,如上面链接中建议的那样。我们将在代码中创建几种不同的类型“Unbox”,因此为每种类型编写 50 行并不吸引人。

我找到了两个替代方案here http://comments.gmane.org/gmane.comp.lang.haskell.libraries/17252。一种替代方法是使用这个包 http://hackage.haskell.org/packages/archive/vector-th-unbox/0.1.0.0/doc/html/Data-Vector-Unboxed-Deriving.html它使用 Template Haskell 派生 Unbox 的实例。 TH 代码如下所示:

derivingUnbox "Zq"
  [d| instance (Foo q, U.Unbox (IntType q)) => Unbox' (ZqBasic q) (IntType q) |]
  [| \ (Zq x) -> x |]
  [| \ x -> Zq x |]

问题是,我无法使用关联类型同义词定义实例 http://www.haskell.org/pipermail/glasgow-haskell-users/2008-October/015794.html(或者我可以吗?)

[一个相关问题:为什么类型同义词实例 http://hackage.haskell.org/trac/haskell-prime/wiki/TypeSynonymInstances,FlexibleInstances 隐含的扩展,不允许联系输入同义词实例?这是从根本上来说是一种不同的野兽吗?]

我目前对该问题的解决方案是将 Zq 重新定义为

newtype Zq q i = Zq i

然后添加等式约束

i~(IntType q)

在涉及 (Zq q i) 的每个实例中,这不是很优雅。我的(工作)拆箱推导变成

derivingUnbox "Zq"
  [d| instance (U.Unbox i, i~IntType q, Foo q) => Unbox' (Zq q i) i |]
  [| \ (Zq x) -> x |]
  [| \ x -> Zq x |]

我觉得我应该能够在不显式暴露类型“i”的情况下完成此任务。我所做的只是将其从关联的类型同义词移至具有相等约束的显式参数。为什么这“从根本上”是一种不同的(而且显然更安全的)方法?有什么方法可以避免添加类型参数“i”并仍然获得自动拆箱派生?

除了额外的类型参数之外,我在使用 TH 包来派生 Unbox for (Vector r) 时遇到了麻烦,也就是说,我想制作 Unbox Vectors 的 Unbox Vector。我的尝试是这样的:

newtype Bar r = Bar (Vector r)

derivingUnbox "Bar"
  [d| instance (Unbox r) => Unbox' (Bar r) (Vector r) |]
  [| \ (Bar x) -> x |]
  [| \ x -> Bar x |]

但我收到(很多)错误,例如:

`basicUnsafeFreeze` is not a (visible) method of class `Data.Vector.Generic.Base.Vector`

我不知道为什么它找不到这个方法,而它对于我的 Zq 类型来说效果很好。


列出的第二种方法above http://comments.gmane.org/gmane.comp.lang.haskell.libraries/17252正在使用扩展 GeneralizedNewtypeDeriving。我发现这种方法的最大问题是我有一些需要拆箱的实际数据(而不是 Newtype)。但是,仅使用扩展名,我应该能够编写

newtype Zq q = Zq (IntType q) deriving (Unbox, M.MVector MVector, G.Vector Vector)

或者至少

newtype Zq q i = Zq i deriving (Unbox, M.MVector MVector, G.Vector Vector)

第一个导致错误:

No instance for (Unbox (IntType q)) arising from the `deriving` clause of a data type declaration
No instance for (M.MVector MVector (IntType q)) ""
No instance for (G.Vector Vector (IntType q)) ""

第二个给出:

No instance for (M.MVector MVector i) ""
No instance for (G.Vector U.Vector i) ""

我不确定为什么它不能导出这些实例,因为上面的帖子让我相信它应该能够导出这些实例。也许我可以摆脱使用与 GeneralizedNewtypeDeriving 相关的类型同义词? (当我需要派生“数据”的 Unbox 时,这仍然(可能)不能解决我的问题。)

感谢您的帮助!


您在这里遇到了几个单独的问题:

TH 方法

是的,关联类型同义词的类实例是非法的

确实,您无法为关联的类型同义词或类型函数定义类实例,这是有充分理由的:编译器无法判断它们是否重叠。例如:

type family F a
instance Eq (F Int)
instance Eq (F Bool)

这些实例是否重叠?鉴于上面的源代码,我们无法判断:这取决于后来某人如何定义实例F。例如,他们可以定义

type instance F Int = Double
type instance F Bool = Double

然后两个实例Eq事实上是重叠的。

您遇到了问题vector-th-unbox package

如果你看一下实际情况Unbox你想要的实例,你实际上并不想要一个实例IntType q;你想要的只是这样:

instance (Unbox (IntType q), Foo q) => Unbox (Zq q) where
    ...

问题是vector-th-unbox包强制你使用假类型类Unbox'传达中间表示类型(IntType q在你的情况下),作为滥用 Template Haskell 语法来传递类型的便捷方法。然后 GHC 看到你写了Unbox' (Zq q) (IntType q)并抱怨。我建议提交一个错误vector-th-unbox包裹。

Unbox for Vector r

我认为路易斯·沃瑟曼(Louis Wasserman)对此进行了报道。

The GeneralizedNewtypeDeriving方法

您遇到的特定编译错误是因为 GHC 无法推断适当的上下文。对于大多数与您遇到的问题类似的问题,StandaloneDeriving语言扩展可以解决您的问题:

deriving instance Unbox (IntType q) => Unbox (Zq q)
deriving instance Unbox (IntType q) => M.MVector MVector (Zq q)
deriving instance Unbox (IntType q) => G.Vector Vector (Zq q)

但不要这样做!

While GeneralizedNewtypeDeriving经常做你想要的事情,它被打破了一些基本方法 http://hackage.haskell.org/trac/ghc/ticket/1496,以及Unbox它产生的实例是完全破碎 http://permalink.gmane.org/gmane.comp.lang.haskell.libraries/17315!因此,在游说 Liyang 解决您当前的问题之后,请坚持使用 TH 方法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

自动派生 Data.Vector.Unbox 以及关联的类型同义词 的相关文章

  • Haskell 中动态规划的高效表

    我已经编码了0 1背包问题 http en wikipedia org wiki Knapsack problem 0 1 knapsack problem在哈斯克尔 我对迄今为止所取得的懒惰和普遍性水平感到相当自豪 我首先提供用于创建和处
  • 为自定义镜头编写类别实例

    我一直在读这个article http www haskellforall com 2012 01 haskell for mainstream programmers 28 html用于理解镜头 我知道这不同于 爱德华 克内特 Edwar
  • Haskell GHC:具有 N 个构造函数的模式匹配的时间复杂度是多少?

    假设我们有以下 Haskell data T T0 T1 T2 TN toInt T gt Int toInt t case t of T0 gt 0 T1 gt 1 T2 gt 2 TN gt N 这里使用什么算法来执行模式匹配 我看到两
  • yesod——密码保护临时站点

    我正在尝试设置 yesod 网络服务器的临时实例 我想知道是否有一些简单的方法可以使整个站点受到密码保护 具体来说 我希望能够提示那些导航到我的网站的人提供凭据 经过身份验证后 它应该像典型站点一样运行 但如果他们无法验证自己的身份 他们就
  • 计算/获取分层数据的“级别”

    好吧 我真的不知道这是否是正确的标题 但我不知道如何称呼它 我的问题是关于我的作业 我现在已经工作了几个小时 主题是 函数式数据结构 我有点陷入困境 我不知道如何继续 所以我需要编写一个具有以下签名的函数 data Heap e t Hea
  • 如何将可选标志解析为 Maybe 值?

    我正在尝试使用optparse 应用程序 https hackage haskell org package optparse applicative 0 11 0 2解析一个Maybe String但我找不到任何地方如何处理Maybe 我
  • 算法 - 如何有效删除列表中的重复元素?

    有一个list L 它包含以下元素任意类型each 如何有效删除此类列表中的所有重复元素 必须保留订单 只需要一个算法 因此不允许导入任何外部库 相关问题 在Python中 从列表中删除重复项以使所有元素都是唯一的最快算法是什么在维持秩序的
  • Haskell printf 转字符串

    Haskell 中有等效的 sprintf 吗 我需要将双精度值转换并格式化为字符串 有没有其他方法而不使用printf什么样的功能 主要问题是要避免 Prelude gt putStrLn myDoubleVal 1 7944444444
  • Haskell 二进制解析

    我一直在尝试在 haskell 中实现一个协议解析器 而且我对这门语言还很陌生 特别是当涉及到 monad 时 我一直在使用binary 0 5 0 2 并描述了协议的标头和所有有效负载 我想要解析的消息如下所示 header payloa
  • Haskell 中的常量变量声明

    要声明常量变量 我可以在 Ruby 中执行以下操作 class COLOR RED 10 BLUE 20 GREEM 30 end COLOR RED回报10 COLOR BLUE回报20 等等 我如何在 Haskell 中实现这一点 我想
  • 为什么haskell中的递归列表这么慢?

    我对 Haskell 很陌生 我在 Haskell 中定义了一个函数 febs Integral a gt a gt a febs n n lt 0 0 n 1 1 n 2 1 otherwise febs n 1 febs n 2 但是
  • 如何找到仅是 2、3 和 5 的幂的倍数的所有数字的列表? [复制]

    这个问题在这里已经有答案了 I am trying to generate a list of all multiples which can be represented by the form where a b and c are w
  • Haskell 测量函数性能

    在 Haskell 中 我如何 简单地 测量函数的性能 例如 运行需要多长时间 或者需要多少内存 我知道分析 但是 是否有一种更简单的方法不需要我对代码进行太多更改 测量运行需要多长时间以及需要多少内存是两个独立的问题 即 基准测试和分析
  • 带有查询参数的渲染 url

    无法找到简单问题的解决方案 答案应该是显而易见的 如何在 hamlet 模板中使用查询参数渲染 url I e ItemsR 将生成http localhost 3000 items我如何生成类似的东西http localhost 3000
  • 如何处理“恐慌:不可能的事情发生了”并在 Haskell 中继续

    我有以下代码 它使用 GHC API 加载模块并获取表达式的类型 typeObjects String gt String gt IO Type typeObjects modules objects do defaultErrorHand
  • 解析 PHOAS 表达式

    我想我理解 PHOAS 参数化高阶抽象语法 我明白了如何漂亮地打印一个表达式 参见http www reddit com r haskell comments 1mo59h phoas for free by edward kmett cc
  • 为什么 exceptT 没有 MonadMask 实例?

    爱德华 克梅特例外情况图书馆不提供单子掩码 https www stackage org haddock lts 7 18 exceptions 0 8 3 Control Monad Catch html t MonadMask实例为Ex
  • 管道中缺少 ResourceT 实例

    我在尝试使用时遇到奇怪的错误ResourceT http hackage haskell org package conduit 1 0 9 1 docs Data Conduit html t 3aResourceT来自管道 1 0 9
  • 地图不是接受一个函数而列表返回一个列表吗?

    map2 List a gt b gt c gt a gt b gt c map2 List f map2 List f a as bs map f a bs map2 List f as bs 这是我的讲座中的一个示例 它尝试将二元函数应
  • 为什么 Haskell 中的点是从右向左排列的?

    如果我们有两个函数 f and g 然后在哈斯克尔h f g相当于h x f g x IE 这些函数从右到左应用于输入 有什么根本原因可以解释为什么它是从右到左 而不是从左到右吗 IE 他们为什么不做h f g相当于h x g f x 反而

随机推荐