[Haskell-cafe] generics and sql
nadine.and.henry at pobox.com
nadine.and.henry at pobox.com
Sun Apr 24 17:30:33 CEST 2011
Thanks for the quick reply Edward. What I'm trying to do is be lazy. I have
a longish data structure, say:
data Loan = Loan {
loan_address :: String,
loan_initialAmount :: Double,
loan_interestRate :: Double,
loan_term:: Int,
loan_originated :: Day,
loan_minimumPayment :: Double,
loan_usualPayment :: Double,
loan_familiarName :: String,
loan_password :: String,
loan_lastVisit :: Day,
loan_nextToLastVisit :: Day,
loan_emailAddress :: String,
} deriving (Read, Show, Eq, Ord, Typeable, Data)
where each component is an instance of (Convertible a SqlValue), and I would
like to be able to say something like:
let vals = magicalGmapIncantation toSql loan
liftIO $ withtransaction db $ \d -> run query vals
of course I could do:
let vals = [toSql (loan_address loan), toSql (loan_initialAmount loan) ...]
but that feels so "dirty," when all those fields are just waiting for me
inside that loan data type.
Best wishes,
H
>>>>> "EZY" == Edward Z Yang <ezyang at MIT.EDU> writes:
EZY> Hmm, this is a bit peculiar. The problem is you don't get control
EZY> over how gmapQ invokes the function toSql: it will only ever be done
EZY> with the type signature Data d => d -> u. There is good reason for
EZY> this too: imagined you tried to run gmapQ toSql on a data-type that
EZY> contained a member that was not convertible to a SqlValue: then it
EZY> ought to fail with a type error!
EZY> You may be able to work around this with more generics madness: use
EZY> Typeable to check if the types of all the fields are kosher, and then
EZY> do an appropriate casts before invoking toSql. But you won't get
EZY> particularly good static guarantees doing it this way.
EZY> So... what are you really trying to do? :-)
------------------------------------------------------------------------
Greetings. I have a feeling that what I am trying to do is easy, I
just don't know how to say it in Haskell. Let's start with:
> {-# LANGUAGE
> DeriveDataTypeable, GeneralizedNewtypeDeriving #-}
>
> import Database.HDBC
> import Data.Typeable (Typeable)
> import Data.Data
> data C = C { str :: String, dbl:: Double }
> deriving (Eq, Ord, Typeable, Data)
>
> a :: C
> a = C "twelve" 12.0
>
Now I load this up in ghci and I can do the following:
toSql . str $ a -- result: SqlString "twelve"
toSql . dbl $ a -- result: SqlDouble 12.0
but what I would really like to do is something like:
gmapQ toSql $ a
which results in:
<interactive>:1:7:
Could not deduce (Convertible d SqlValue)
arising from a use of `toSql'
from the context (Data d)
bound by a type expected by the context: Data d => d -> SqlValue
at <interactive>:1:1-11
Possible fix:
add (Convertible d SqlValue) to the context of
a type expected by the context: Data d => d -> SqlValue
or add an instance declaration for (Convertible d SqlValue)
In the first argument of `gmapQ', namely `toSql'
In the expression: gmapQ toSql
In other words, I'm looking for a function with a signature:
(Whatever Instances I neeed here) => a -> [SqlValue]
I have tried various incantations of type signatures, but thus far I
can't get it right. Can someone point me in the right direction? Thanks.
--
Nadine & Henry Laxen Belle, Venus, Aphrodite
10580 N. McCarran Blvd. Adonis, Miss Parker & Jarod
Suite 115-396 Via Alta # 6
Reno, Nevada Chapala, Jalisco, Mexico
89503-1896 CP 45900
The rest is silence. (Hamlet)
More information about the Haskell-Cafe
mailing list