[Haskell-cafe] Newtype, Data.Text and instance declarations...
Guy-Laurent Subri
guy-laurent at subri.ch
Fri Apr 12 04:40:34 UTC 2019
Hi all,
There are a few things that I don't understand involving Data.Text and
instance declarations...
I'm building a small web app to practise Haskell and am using the
SQLite.Simple library.
I have defined a few types and functions like so:
'''
data BookmarkDB = BookmarkDB Connection Table
newtype Table = Table Text
instance ToField Table where
toField = SQLText
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
executeNamed conn query [":table" := table]
return $ BookmarkDB conn table
'''
1. My first question is about the instance declaration. Why would
'''
instance ToField Table where
toField = SQLText
'''
return this error ?
'''
Couldn't match type ‘Table’ with ‘Text’
Expected type: Table -> SQLData
Actual type: Text -> SQLData
• In the expression: SQLText
In an equation for ‘toField’: toField = SQLText
In the instance declaration for ‘ToField Table’
'''
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?
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).
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.
I've also noticed that this will help:
'''
initDB :: FilePath -> Table -> IO BookmarkDB
initDB fp t@(Table 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 t
'''
But I *really* don't get why! The most confusing part for me is that the
last initDB function will do exactly what I want it to do, but I am
unable to understand why it works...Why am I able to concatenate the
'table' now and not before and why is 't' of a different type than
'table'?
All of this is very confusing and I find myself unable to reason about
it. Sorry if this is a big/messy question. I hope everything is clear
enough to answer...
Thank you all!
More information about the Haskell-Cafe
mailing list