Haskell 多态返回类型和;刚性类型变量“;哈斯克尔错误
有一个简单的记录Haskell 多态返回类型和;刚性类型变量“;哈斯克尔错误,haskell,vector,Haskell,Vector,有一个简单的记录列va,它保存了数据.Vector族中的向量(因此v可以是向量。未装箱的,只需向量等),它的名称和类型(简单的枚举,如ADT支持的类型)。我希望能够使用binary包对其进行序列化。为此,我尝试在下面定义一个Binary实例 现在,put工作正常,但是当我尝试在get函数中定义反序列化,并希望将特定类型设置为基于colType返回的rawVector时(U.Vector Int64当它是PInt时,U.Vector Double当它是PDouble等)我收到了这个错误消息: 无法
列va
,它保存了数据.Vector
族中的向量(因此v
可以是向量。未装箱的,只需向量
等),它的名称和类型(简单的枚举,如ADT支持的类型
)。我希望能够使用binary
包对其进行序列化。为此,我尝试在下面定义一个Binary
实例
现在,put
工作正常,但是当我尝试在get
函数中定义反序列化,并希望将特定类型设置为基于colType
返回的rawVector
时(U.Vector Int64
当它是PInt
时,U.Vector Double
当它是PDouble
等)我收到了这个错误消息:
无法将类型v
与U.Vector
v
是一个刚性类型变量,由位于src/Quark/Base/Column.hs的实例声明绑定。hs
:75:10
预期类型:va
实际类型:U.Vector Int64
错误
有没有更好的方法来实现我的目标-基于colType
值反序列化不同类型的Vector
s,还是我一直在为所有可能的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}
{-#语言重载字符串、TransformListComp、RankNTypes、,
TypeSynonyment实例、FlexibleInstances、OverloadedList、DeriveGeneric#-}
{-#语言多段类型类,灵活上下文,
TypeFamilies、ScopedTypeVariables、InstanceSigs#-}
将限定的Data.Vector.Generic作为G导入
导入符合条件的Data.Vector.unbox为U
数据列va=列{rawVector::G.Vector va=>va,colName::Text,colType::SupportedTypes}
实例(G.Vector va,Binary(va))=>Binary(列va),其中
put列{rawVector=vec,colName=cn,colType=ct}=do-put(fromnum-ct)>>put-cn>>put-vec
get=dot正如注释所说,您可以简单地不使用类型的大小写,而总是调用
vec <- get
return Column {rawVector = vec, colName = nm, colType = pt}
现在,您可以在需要的地方在调用站点强制执行G.Vector
约束…正如注释所述,您可以简单地不使用类型的大小写,而是始终调用
vec <- get
return Column {rawVector = vec, colName = nm, colType = pt}
现在,您可以在必要的呼叫站点强制执行G.Vector
约束…您实际遇到的问题(或者如果您还没有遇到,您将会遇到)您正试图根据输入值确定结果类型。您根本无法这样做。您可以聪明地将结果类型锁定在一个框中,然后扔掉键,这样从外部看,该类型似乎正常,但之后您无法对其执行任何操作,因为您将类型锁定在一个框中,然后扔掉键。您可以存储额外的i使用GADTs并用类型类实例将其装箱,但这仍然不是一个好主意
如果您只需为列提供两个构造函数,以反映是否存在Int
s或Double
s的向量,您的生活就会轻松得多
但实际上,不要这样做,只需让自动派生的二进制实例将任何可反序列化的值反序列化到向量中即可
data Column a = ... deriving (Binary)
使用DeriveAnyClass
扩展,您可以派生任何具有Generic
实现的类(它是Binary
实现的)。然后在需要时反序列化一个列Double
或列Int
。您实际遇到的问题(或者如果您还没有,您会遇到)您正试图根据输入值确定结果类型。您根本无法这样做。您可以聪明地将结果类型锁定在一个框中,然后扔掉键,这样从外部看,该类型似乎正常,但之后您无法对其执行任何操作,因为您将类型锁定在一个框中,然后扔掉键。您可以存储额外的i使用GADTs并用类型类实例将其装箱,但这仍然不是一个好主意
如果您只需为列提供两个构造函数,以反映是否存在Int
s或Double
s的向量,您的生活就会轻松得多
但实际上,不要这样做,只需让自动派生的二进制实例将任何可反序列化的值反序列化到向量中即可
data Column a = ... deriving (Binary)
使用DeriveAnyClass
扩展,您可以派生任何具有Generic
实现的类(它是Binary
实现的)。然后在需要时反序列化列Double
或列Int
。您真正想要表示的类型是
data Column v = Column (Either (v Int) (v Double))
但是这种表示法可能不令人满意。那么,如何在构造函数的“顶层”使用向量本身编写这种类型呢
首先,从类型级别(而不是值级别)的总和表示(或Int-Double
)开始:
data IsSupportedType a where
TInt :: IsSupportedType Int
TDouble :: IsSupportedType Double
从这里看,列
实际上非常简单:
data Column v a = Column (IsSupportedType a) (v a)
但你可能需要一个存在量化的a
来按照你的意愿使用它:
data Column v = forall a . Column (IsSupportedType a) (v a)
二进制实例如下所示:
instance (Binary (v Int), Binary (v Double)) => Binary (Column v) where
put (Column t v) = do
case t of
TInt -> put (0 :: Int) >> put v
TDouble -> put (1 :: Int) >> put v
get = do
t :: Int <- get
case t of
0 -> Column TInt <$> get
1 -> Column TDouble <$> get
实例(二进制(v Int),二进制(v Double))=>二进制(v列),其中
put(列tv)=do
案例t
色调->放置(0::Int)>>放置v
t双重->放置(1::Int)>>放置v
得到=做
t::Int列着色获取
1->列t双倍获取
请注意,Vector
中没有固有的依赖性-v
可以是任何东西。您真正想要表示的类型是
data Column v = Column (Either (v Int) (v Double))
但这种表示法可能不能让你们满意。那个么你们如何用向量itse来写这种类型呢