
Tim Docker writes: : | The list being folded over | is implied by the DB query, is accessible through the IO monad. | Hence a parameter is not required. It would really be: | | doquery :: Process -> String -> b -> (b -> IO (b,Bool)) -> IO b : | One thing that I am unsure about is whether the column value | accessing functions that I specified before | | stringv :: Process -> CInt -> IO String | doublev :: Process -> CInt -> IO Double | intv :: Process -> CInt -> IO Int | | should return actions in the IO monad as above, or instead should | be in some other DBQuery monad, that trivially extends the IO monad, | but is only valid inside the doquery call. This would have the benefit | of restricting the column access functions to inside a query via the | type system. How about introducing a Cursor abstract data type? doquery :: Process -> String -> b -> (Cursor -> b -> IO (b, Bool)) -> IO b stringv :: Cursor -> CInt -> IO String doublev :: Cursor -> CInt -> IO Double intv :: Cursor -> CInt -> IO Int This achieves the restriction you're after, because doquery is the only exported producer of Cursor, and stringv etc. are the only exported consumers of Cursor. It also has the benefit that the function you pass to doquery can make other calls to doquery, without mucking up the 'current row' state. There would be one current row per Cursor, not one per Process. | I'd also probably use a typeclass to specify a single colv function. | ie: | | class DBCol a where | colv :: DBQuery a | | instance DBCol String where... | instance DBCol Double where... Good idea. The user can always use explicit type signatures to resolve ambiguity, and even then the code size will be about the same as with stringv etc. - Tom