【发布时间】:2016-03-17 17:52:31
【问题描述】:
有一个简单的记录Column v a 包含来自Data.Vector 家族的Vector(因此v 可以是Vector.Unboxed,只是Vector 等),它的名称和类型(类似简单的枚举ADT SupportedTypes)。我希望能够使用binary 包对其进行序列化。为此,我尝试在下面定义一个Binary 实例。
现在put 工作正常,但是当我尝试在get 函数中定义反序列化并希望将特定类型设置为基于colType 返回的rawVector(U.Vector Int64 时它是 PInt、U.Vector Double,当它是 PDouble 等) - 我收到此错误消息:
无法将类型
v与U.Vector匹配
v是一个刚性类型变量,由src/Quark/Base/Column.hs:75:10 处的实例声明绑定预期类型:
v a实际类型:
U.Vector Int64
错误。
有没有更好的方法来实现我的目标 - 根据 colType 值反序列化不同类型的 Vectors,还是我坚持为所有可能的 Vector / 原始类型组合定义 Binary 实例?不应该这样……
对 Haskell 有点陌生,感谢任何帮助!谢谢!
{-# LANGUAGE OverloadedStrings, TransformListComp, RankNTypes,
TypeSynonymInstances, FlexibleInstances, OverloadedLists, DeriveGeneric #-}
{-# LANGUAGE MultiParamTypeClasses, FlexibleContexts,
TypeFamilies, ScopedTypeVariables, InstanceSigs #-}
import qualified Data.Vector.Generic as G
import qualified Data.Vector.Unboxed as U
data Column v a = Column {rawVector :: G.Vector v a => v a, colName :: Text, colType :: SupportedTypes }
instance (G.Vector v a, Binary (v a)) => Binary (Column v a) where
put Column {rawVector = vec, colName = cn, colType = ct} = do put (fromEnum ct) >> put cn >> put vec
get = do t <- get :: Get Int
nm <- get :: Get Text
let pt = toEnum t :: SupportedTypes
case pt of
PInt -> do vec <- get :: Get (U.Vector Int64)
return Column {rawVector = vec, colName = nm, colType = pt}
PDouble -> do vec <- get :: Get (U.Vector Double)
return Column {rawVector = vec, colName = nm, colType = pt}
更新感谢您在下面的所有答案,一些非常好的想法!很明显,我想做的事情是不可能正面实现的——这就是我的答案。但是其他建议的解决方案本身就是一个很好的阅读,非常感谢!
【问题讨论】:
-
将
vec <- get :: Get (U.Vector Int64)更改为vec <- get并让类型推断解决。vec <- get :: Get (U.Vector Double)相同。当然,解析的向量不会是整数或双精度向量(它将是使用您的函数的人指定的任何内容),但这不是二进制的问题 - 您的数据类型并不代表您认为它的作用。你可能想要existential quantification。 -
get withoutqualification 要么抱怨它无法确定类型,要么读取双精度字节等,如下所述
-
对存在数据类型进行了更多阅读,并开始意识到@user2407038 你是绝对正确的。这似乎完全实现了我想要的 - 不同类型的向量集合,我可以使用通用向量接口对其进行操作。