[Takusen] working out how to use bind variables
Michael Litchard
michael at schmong.org
Thu Aug 12 11:09:57 EDT 2010
It works, but I am confused about the final return.
My understanding is that return takes a computation from one monad,
and puts it in another . In this case IO (). But the pattern I have
seen is this,
return $ some computation
so when I see
return ()
I am not sure what that means.
On Wed, Aug 11, 2010 at 7:06 PM, Jason Dagit <dagit at codersbase.com> wrote:
> I explained this in IRC but I'm also replying here so that the solution will
> appear together with the question when other people search for it.
>
> On Wed, Aug 11, 2010 at 11:45 AM, Michael Litchard <michael at schmong.org>
> wrote:
>>
>> Here's some toy code I have been playing with. The first few attempts
>> work fine, but the final line, where I try to use bind variables,
>> becomes a problem.
>>
>>
>>
>> > import Database.PostgreSQL.Enumerator
>> > import Database.Enumerator
>>
>> > main :: IO ()
>> > main = do
>> > let connection = connect [CAdbname "tutorialDB"]
>> > let foo = "test"
>> > let bar = 42
>> > withSession connection (execDDL (sql "create table activities (Activity
>> > char(20) PRIMARY KEY, cost int)"))
>> > withSession connection (execDDL (sql "create table students (Student
>> > char (20), ID int PRIMARY KEY)"))
>> > withSession connection (execDDL (sql "create table participants
>> > (Activity char (20) REFERENCES activities , ID int PRIMARY KEY)"))
>> > withSession connection (execDDL (sql "insert into activities
>> > (Activity,Cost) values ('golf', 27)"))
>> > withSession connection (execDML (cmdbind "insert into activities
>> > (Activity, Cost) values (?, ?)" [bindP foo, bindP bar]))
>>
>>
>> tutorial.lhs:16:26:
>> Couldn't match expected type `()' against inferred type `Int'
>> Expected type: DBM mark Session ()
>> Inferred type: DBM mark Session Int
>> In the second argument of `withSession', namely
>> `(execDML
>> (cmdbind
>> "insert into activities (Activity, Cost) values (?, ?)"
>> [bindP foo, bindP bar]))'
>> In the expression:
>> withSession
>> connection
>> (execDML
>> (cmdbind
>> "insert into activities (Activity, Cost) values (?, ?)"
>> [bindP foo, bindP bar]))
>>
>>
>> I know this means I need to fix the type, but I don't know how. I've
>> been looking at the code used for testing, plus the usage examples
>> from Enumerator.lhs. Haven't quite got it. Any help pointing me in the
>> right direction would be much welcome.
>
> The problem is that withSession has this type:
>> withSession :: (Typeable a, IE.ISession sess) =>
>> IE.ConnectA sess -> (forall mark. DBM mark sess a) -> IO a
> execDML has this type:
>> execDML :: IE.Command stmt s => stmt -> DBM mark s Int
> So, your call withSession (execDML ...), must have type:
> IO Int
> The type of main is IO (). Since the call to withSession appears last in
> main there is a conflict between the Int that withSession is trying to
> return and the type of main.
> One fix is to add a line right after your last withSession that is just
> "return ()". Once you do that, you'll start getting a crazy error message
> about overlapping instances. The problem in that case is that bar has
> polymorphic type, "Num a => a". You'll need to provide an explicit type
> signature for bar. A working version of your program looks like this:
> \begin{code}
> import Database.PostgreSQL.Enumerator
> import Database.Enumerator
> main :: IO ()
> main = do
> let connection = connect [CAdbname "tutorialDB"]
> let foo = "test"
> let bar :: Int
> bar = 42
> withSession connection (execDDL (sql "create table activities (Activity
> char(20) PRIMARY KEY, cost int)"))
> withSession connection (execDDL (sql "create table students (Student char
> (20), ID int PRIMARY KEY)"))
> withSession connection (execDDL (sql "create table participants (Activity
> char (20) REFERENCES activities , ID int PRIMARY KEY)"))
> withSession connection (execDDL (sql "insert into activities
> (Activity,Cost) values ('golf', 27)"))
> withSession connection (execDML (cmdbind "insert into activities
> (Activity, Cost) values (?, ?)" [bindP foo, bindP bar]))
> return ()
> \end{code}
> I hope that helps!
> Jason
More information about the Takusen
mailing list