gpt4 book ai didi

haskell - 为类型匹配定义 Storable 的受限子集

转载 作者:行者123 更新时间:2023-12-01 11:53:38 24 4
gpt4 key购买 nike

我收到以下代码的错误 - 我怀疑它与 dispatch 函数的类型签名有关,该函数返回 Storable a 类型的 Vector 。更新 dispatch 函数类型签名以仅在类型签名中执行 Int32CChar 的简单方法是什么:

{-#  LANGUAGE BangPatterns #-}
import Data.Vector.Storable as SV
import Foreign.C.Types (CChar)
import GHC.Int (Int32)

data AList = I {-# UNPACK #-} !(SV.Vector Int32)
| S {-# UNPACK #-} !(SV.Vector CChar)


dispatch :: (Storable a) => AList -> SV.Vector a
dispatch (I x) = x
dispatch (S x) = x

ghci 7.4.1 错误:

    test.hs:11:18:
Couldn't match type `CChar' with `Int32'
Expected type: Vector a
Actual type: Vector Int32
In the expression: x
In an equation for `dispatch': dispatch (I x) = x
Failed, modules loaded: none.

我在假设我的错误诊断是正确的情况下问这个问题。如果我的诊断不正确,我将不胜感激有关如何修复上述错误的指示。

最佳答案

类型签名

dispatch :: (Storable a) => AList -> SV.Vector a

说“给我一个 AList,我会给你一个 SV.Vector a 用于任何 a 你想要的,只要它是 Storable 的一个实例”。那是不对的!对于任何给定值,您只能提供一个 a,并且选择它,而不是调用代码。如果您显式添加量词,问题可能更容易发现:

dispatch :: forall a. (Storable a) => AList -> SV.Vector a

你真正想说的是“给我一个 AList,我给你一个 SV.Vector a for some我选择的 a,但我保证它将是 Storable 的一个实例。为此,我们需要一个存在类型:

data SomeSVVector = forall a. (Storable a) => SomeSVVector (SV.Vector a)

dispatch :: AList -> SomeSVVector
dispatch (I x) = SomeSVVector x
dispatch (S x) = SomeSVVector x

(为此你需要 {-# LANGUAGE ExistentialQuantification #-}。)

这给 SomeVVector 类型:

SomeVVector :: (Storable a) => SV.Vector a -> SomeVVector

然后您可以使用 case dispatch x of SomeSVVector vec -> ...dispatch 的结果中取出 SV.Vector .然而,这可能不是那么有用:因为存在性可以包含一个向量,其元素是 Storableany 实例, 操作您可以对里面的数据执行 Storable 类提供的数据。如果您想要用户代码可以分析和“分派(dispatch)”类型的东西,您将需要一个带标签的联合 — 这正是您的 AList 类型已经存在的。

如果您确实想走存在主义路线,那么我建议将您自己的类型类定义为 Storable 的子类,其中包含您可能希望对内部值执行的所有操作。至少,您可能希望将 Integral 添加到 SomeSVVector 的约束中。


正如您在评论中提到的,如果您不介意 Int32AListCChar 的 AList 具有不同的类型,您可以使用 GADT:

data AList a where
I :: {-# UNPACK #-} !(SV.Vector Int32) -> AList Int32
S :: {-# UNPACK #-} !(SV.Vector CChar) -> AList CChar

dispatch :: AList a -> SV.Vector a
dispatch (I x) = x
dispatch (S x) = x

这里,AList 本质上是 SV.Vector 的一个版本,它只适用于某些元素类型。但是,dispatch 并不是那么有用——在使用 dispatch 将其取出后,没有真正的方法可以“返回”到 AList >,因为 GADT 模式匹配提供的类型统一仅适用于显式模式匹配;您无法判断 dispatch 的结果是 SV.Vector Int32 还是 SV.Vector CChar。有点像

dispatch :: (SV.Vector Int32 -> r) -> (SV.Vector CChar -> r) -> AList a -> r

会起作用,但这等同于(并且比)原始标记联合版本上的模式匹配。

我认为没有合理的方法来定义有用的dispatch;我建议改为在您的原始 AList 定义上使用显式模式匹配。

关于haskell - 为类型匹配定义 Storable 的受限子集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9178308/

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