转换为字符串中的类型化值



我有一个包含值和类型列表的文件,在读取它们之后,我需要将它们放入数据库中。为此,我需要为插入函数提供正确类型的元组,所以我尝试使用类似的东西来转换值

toProperType :: String -> String -> a  
toProperType tp val =
  case tp of
    "string" -> val            -- ::String
    "int"    -> toIntType val  -- ::Int64
    "bigint" -> toIntType val  -- ::Int64
    "integer"-> toIntType val    
    "utcdate"-> toDateType val -- :: UTCTime
    "double" -> toDoubleType val -- :: Double

失败了

无法将预期类型"a"与实际类型"Double"匹配"a"是受约束的刚性类型变量

我认为这是正确的。

实现此功能的正确方法是什么?

也许我需要一些扩展或用TH生成单独的函数(但不确定如何调度它们)

这里的问题是函数类型中-> a的含义。如果你的函数实际上有这种类型,那么无论调用你的函数的人都应该能够指定他们选择的具体类型(你甚至可能不在范围内),然后期望你的函数像类型一样工作

String -> String -> MyCustomType

然而,这显然不是你想的。你的意思不是"对于所有类型的a,我有一个函数…",你的意思是"对于任何两个字符串,都有一个a类型的值"。这个想法,你可以选择类型变量而不是调用者,被称为"存在量化",GHC确实支持它。然而,我真的不认为这是你想要做的。毕竟,当你真正使用这个函数时,你可能希望能够判断你是否得到了UTCTimeDouble或其他什么。既然你不能用存在量化来做到这一点(就像你不能在多元数学函数中对类型变量进行大小写一样),我们应该创建一个自定义的数据类型:

data Dyn = String String | Int Int | BigInt Integer | UTCDate UTCTime ...

等等。也就是说,你为你的类型可能返回的每个情况列出一个显式构造函数,然后你的函数将读取

toProperType :: String -> String -> Dyn  
toProperType tp val =
  case tp of
    "string" -> String val            -- ::String
    "int"    -> Int $ toIntType val  -- ::Int64
    "bigint" -> BigInt $ toIntType val  -- ::Int64
    "integer"-> Integer $ toIntType val    
    "utcdate"-> UTCDate $ toDateType val -- :: UTCTime
    "double" -> Double $ toDoubleType val -- :: Double

这就是严肃的Haskell库处理JSON解析之类的事情的方式,所以你是一个好公司。现在它的类型很好,调用此函数的人只对Dyn值进行大小写,并根据返回的类型决定要做什么。

最新更新