[Haskell-cafe] Type classes and definite types
Bryn Keller
xoltar at xoltar.org
Thu May 5 13:17:45 EDT 2005
Hi folks,
I set out to perform a (seemingly) simple experiment last night. I
thought I'd try to get used to the HSQL library by writing a little app
that would take an SQL query on the command line, run it, and print the
results. So far, this seems to be impossible. I'd like to know if
there's a way around this problem, or if this is actually insurmountable
(short of generating and compiling new Haskell programs for each query).
The HSQL library works quite well for queries whose types you know in
advance, as in
printRow stmt = do
(id :: Int) <- getFieldValue stmt "ID"
(code :: String) <- getFieldValue stmt "Code"
(name :: String) <- getFieldValue stmt "Name"
putStrLn (unwords [show id, show code, show name])
however, it doesn't work at all if you can't specify the types at
compile time:
printRow' (names,types,nulls) stmt = do
values <- mapM (getFieldValue stmt) names
putStrLn $ unwords (map show values)
The problem is that getFieldValue returns a value of type (SqlBind a) =>
a. That is, there's no type information associated with this return
value other than it's a valid SQL value. There are no operations in the
SqlBind class, it's just a marker as near as I can tell. So when you
call getFieldValue, the exact type has to be fixed in some way (by
annotations in this example). If the type is not fixed, it can't be
used, as shown by the fact that printRow' won't compile. I think this is
just the same problem we have with other type classes, e.g., (show
(read s)), not anything new. The question is, what can be done about it?
Is there anything I, the user can do about it, or can only the library
authors solve this problem? Is there something we can change in Haskell
to make this sort of thing possible?
Thanks,
Bryn
import Database.HSQL
import Database.HSQL.ODBC
import System.Environment (getArgs)
main = do
(connString:sql:_) <- getArgs
conn <- connect connString "" ""
putStrLn "Connected"
stmt <- query conn sql
putStrLn $ "Ran query " ++ sql
let info = unzip3 $ getFieldsTypes stmt
putStrLn (show info)
forEachRow' printRow stmt
printRow stmt = do
(id :: Int) <- getFieldValue stmt "ID"
(code :: String) <- getFieldValue stmt "Code"
(name :: String) <- getFieldValue stmt "Name"
putStrLn (unwords [show id, show code, show name])
printRow' (names,types,nulls) stmt = do
values <- mapM (getFieldValue stmt) names
putStrLn $ unwords (map show values)
More information about the Haskell-Cafe
mailing list