我不明白如何在database.HDBC中使用fromSql。
*Main> toSql "foobar"
SqlString "foobar"
直到这里,我觉得很舒服,我有一些类型SqlString
现在,尝试一些往返:
*Main> fromSql $ toSql "foobar"
<interactive>:4:1: error:
* Non type-variable argument
in the constraint: Data.Convertible.Base.Convertible SqlValue a
(Use FlexibleContexts to permit this)
* When checking the inferred type
it :: forall a. Data.Convertible.Base.Convertible SqlValue a => a
好的,我根据这个帖子Haskell : Use -XFlexibleContexts to permit this?
打开了FlexibleContexts*Main> :set -XFlexibleContexts
*Main> fromSql $ toSql "foobar"
<interactive>:8:1: error:
* No instance for (Data.Convertible.Base.Convertible SqlValue ())
arising from a use of `it'
* In the first argument of `print', namely `it'
In a stmt of an interactive GHCi command: print it
仍然是KO,我在这里明白,无论往返行程创造什么类型,这些东西都不是印刷品的有效论据。
我正在检查类型:
*Main> res = fromSql $ toSql "foobar"
*Main> :t res
res :: Data.Convertible.Base.Convertible SqlValue a => a
在这里我迷失了......我希望有[char]或String之类的东西。
答案 0 :(得分:1)
您只需要添加一个类型注释即可使typechecking成功:
λ> fromSql $ toSql "foobar" :: String
"foobar"
如果您使用更多上下文代码,则可以跳过注释,如果可以推断,例如:
λ> putStrLn $ fromSql $ toSql "foobar"
foobar
由于putStrLn
的类型为String -> IO ()
,因此会自动推断出类型。
试图给出一些直觉,说明为什么需要这样做:
toSql
的类型是:
toSql :: Convertible a SqlValue => a -> SqlValue
请注意,结果类型(SqlValue
)没有任何关于它包含的类型的参数 - 它只是一个黑盒子,可以是一个字符串,数字等。鉴于此,并查看fromSql
的类型:
fromSql :: Convertible SqlValue a => SqlValue -> a
...我们可以看到它需要这个黑盒子,并且必须从中返回特定类型的值。它不能将此类型限制为String
或Int
,因为它必须能够根据黑匣子内部的内容以及黑匣子本身返回不同的类型在编译时没有透露任何关于它内部信息的信息,所以它无法利用它。
它唯一可能的返回类型是a
(遵守约束Convertible SqlValue a
),所以你必须添加类型约束来强制它进行类型检查。