
On Fri, Apr 12, 2019 at 12:42 AM Guy-Laurent Subri
I've noticed that if I write ''' instance ToField Table where toField (Table t) = SQLText t '''
I have no error and it compiles. I don't get it, what is 'toField' supposed to receive except a Table?
Haskell does not automatically "convert" types. If something wants a Text, it will not accept a Table, even though that Table is just a wrapper around a Text. You must unwrap it to get the Text inside, which is what the (Table t) pattern is doing: matches a Table by its constructor, and gives you the contained Text bound to "t". This is somewhat more obvious when you have a type with multiple fields, or with multiple constructors, since pattern matching then lets you access all the fields, and you can have multiple patterns matching different constructors. data Foo = Foo Int Text someFoo (Foo i t) = -- do something with the Int i and Text t here data Foo = FooI Int | FooT Text someFoo (FooI i) = -- do something with the Int i here someFoo (FooT t) = -- do something with the Text t here (You can of course also combine them, multiple constructors each with zero or more fields.) 2. My second question is concerning the initDB function. If I write it
that way, the code compiles, but I get an error during execution:
bkmrk: SQLite3 returned ErrorError while attempting to perform prepare "CREATE TABLE IF NOT EXISTS :table (url TEXT, tags TEXT, date INTEGER)": near ":table": syntax error
I don't understand what is wrong with the code and I doubt that my query is wrong because everything works with the last code snippet I wrote (see question #3).
In general, you can't use that kind of substitution with SQL Data Definition Language (e.g. CREATE TABLE), nor is it generally usable to replace table or column names, only values. You need to concatenate the actual table name into the command, not a SQL string-like value nor an embedded SQL placeholder. 3. Trying to get around the error I've noticed a few things. If I try to
write this instead:
''' initDB :: FilePath -> Table -> IO BookmarkDB initDB fp table = do let query = Query ("CREATE TABLE IF NOT EXISTS " <> table <> " (url TEXT, tags TEXT, date INTEGER)") conn <- open fp execute_ conn query return $ BookmarkDB conn table '''
it doesn't compile because table is of type Table and not Data.Text.Internal.Text, which I get, but I don't know what is the Haskell way of resolving this.
Same as your first question: initDB fp t@(Table table) = do -- which unwraps the Table and gives you the Text within it as "table". But you also need the actual Table value, since you use it in the last line of your function, so you also need the as-pattern. -- brandon s allbery kf8nh allbery.b@gmail.com