[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