database.HDBC中fromSql使用困惑及往返转换报错咨询
解决HDBC中fromSql往返转换的类型错误问题
我完全懂你这会儿的困惑——HDBC的fromSql因为多态特性的缘故,在你没明确告诉它要转成什么类型的时候,编译器根本猜不到你想要的结果类型,这就是报错的核心原因。
咱们拆解下问题:
- 首先,
toSql "foobar"能顺利得到SqlString "foobar",是因为针对字符串输入,toSql的目标类型是明确的; - 但
fromSql的类型签名是Convertible SqlValue a => SqlValue -> a——它可以把SqlValue转换成任何实现了Convertible SqlValue a约束的类型a,可编译器没法凭空知道你要的是String、Maybe String还是其他类型,于是就抛出了那个关于FlexibleContexts和多态类型的错误。
最直接的解决办法:显式指定目标类型
你只需要给fromSql的结果加上类型注解,明确告诉编译器你要转成String就行:
*Main> fromSql (toSql "foobar") :: String "foobar"
或者在GHCi里用绑定的方式:
*Main> let res = fromSql (toSql "foobar") :: String *Main> res "foobar"
关于FlexibleContexts的补充说明
错误提示里提到的FlexibleContexts是Haskell的一个语言扩展,它允许类型约束里出现非类型变量的参数(比如这里的SqlValue)。不过就算你开启这个扩展(在GHCi里输入:set -XFlexibleContexts),你还是得明确指定目标类型——因为编译器依然没法推断你要的a是什么,所以显式类型注解才是最省心的解决方案。
进阶技巧:封装辅助函数
如果你经常需要在String和SqlValue之间往返转换,可以封装两个简单的辅助函数,省去每次写类型注解的麻烦:
sqlToString :: SqlValue -> String sqlToString = fromSql stringToSql :: String -> SqlValue stringToSql = toSql
之后用起来就很顺畅:
*Main> sqlToString (stringToSql "foobar") "foobar"
内容的提问来源于stack exchange,提问作者sandwood
相关产品推荐
相关产品推荐

