I am trying to use the Beam Haskell library. Consider the following two snippets:
Version 1:
getDb = open "shoppingcart1.db"
runDebug conn = runBeamSqliteDebug putStr conn
runDebugInDb actions = do conn <- getDb
runDebug conn actions
Version 2:
dbFile = "shoppingcart1.db"
getDb = open dbFile
runDebug conn = runBeamSqliteDebug putStr conn
runDebugInDb actions = do conn <- getDb
runDebug conn actions
I would expect that the type inference would be the same. But the type inferred for runDebugInDb is different, even when the inferred type for runDebug and getDb are the same.
ghci for version 1:
λ> :t (getDb, runDebug, runDebugInDb)
(getDb, runDebug, runDebugInDb)
:: (IO Connection, Connection -> SqliteM a -> IO a,
SqliteM b -> IO b)
ghci for version 2:
λ> :t (getDb, runDebug, runDebugInDb)
(getDb, runDebug, runDebugInDb)
:: (IO Connection, Connection -> SqliteM a -> IO a,
SqliteM () -> IO ())
The correct behavior is the first snippet, so that the query can return the result of the query. To get the second snippet to work, I have to explicitly annotate the type of runDebugInDb.
Being new to Haskell, I don't understand well how the type inference system works. Why does the runDebugInDb type get inferred differently in these two?
Update 1: A minimal example can be found here. This also shows the enabled extensions, which were from the Beam tutorial.
For some reason the behavior is a little bit different: the types from ghci are:
running version 1:
λ> :t (getDb, runDebug, runDebugInDb)
(getDb, runDebug, runDebugInDb)
:: (IO Connection, Connection -> SqliteM a -> IO a,
SqliteM b -> IO b)
running version 2:
λ> :t (getDb, runDebug, runDebugInDb)
(getDb, runDebug, runDebugInDb)
:: (IO Connection, Connection -> SqliteM a -> IO a,
SqliteM ghc-prim-0.6.1:GHC.Types.Any
-> IO ghc-prim-0.6.1:GHC.Types.Any)
Update 2: Turning off the ExtendedDefaultRules extension allowed this to work. Enabling the MonomorphismRestriction extension did not appear to change anything.
It seems that ExtendedDefaultRules changes the interpretation of literals. If I understand correctly, the "shoppingcart1.db" string literal is carried along to runDebug and is interpreted differently in that function. Is this a correct interpretation, and how can I be sure about when this extension makes a difference?
Update 3: It seems that ExtendedDefaultRules didn't actually change the behavior. It turns out the behavior is different if I load the entire file into ghci as opposed to copying the lines into ghci and running them one-by-one. The behavior is what I originally reported if I load the entire file (:l TypeInferenceExample.hs) but the type inference is the same if the lines are copied into ghci.
(I thought I was unsetting the ExtendedDefaultRules extension in ghci but actually wasn't.)