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来写这种类型呢