[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