Yesod 1.6 was released in February of this year. This new version changes how subsites are implemented, which breaks most Yesod web applications. I did not find many good resources describing how to migrate web applications to 1.6, so I am documenting the steps I took to fix my website. It was not immediately obvious what changes needed to be made, so hopefully this is helpful for others.
My website was originally running on Stackage LTS 9.2, so I upgraded to LTS 12.2 by updating my stack.yaml
file:
resolver: lts-12.2
I recompiled the website with stack build
, but this gave me version conflicts for dependencies. I fixed the version conflicts for dependencies in my <package>.cabal
file by widening the accepted versions in the build-depends
section (I actually just got rid of most of the version constraints). If you use hpack, you'll need to edit the dependencies in your package.yaml
file.
After fixing the version conflicts, I started getting compiler errors:
src/Foundation.hs:94:5: error:
‘shouldLog’ is not a (visible) method of class ‘Yesod’
|
94 | shouldLog app _source level =
| ^^^^^^^^^
It looks like shouldLog
has been removed. I just commented it out in src/Foundation.hs
.
Then I got the following errors:
src/Foundation.hs:147:9: error:
• Couldn't match kind ‘* -> *’ with ‘*’
When matching types
m0 :: * -> *
site0 :: *
Expected type: YesodDB site0 (AuthenticationResult App)
Actual type: ReaderT
(YesodPersistBackend site0) (t0 m0) (AuthenticationResult App)
• In a stmt of a 'do' block:
x <- getBy $ UniqueUser $ credsIdent creds
In the second argument of ‘($)’, namely
‘do x <- getBy $ UniqueUser $ credsIdent creds
case x of
Just (Entity uid _) -> return $ Authenticated uid
Nothing -> do ...’
In the expression:
runDB
$ do x <- getBy $ UniqueUser $ credsIdent creds
case x of
Just (Entity uid _) -> return $ Authenticated uid
Nothing -> do ...
|
147 | x <- getBy $ UniqueUser $ credsIdent creds
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
It looks like the authentication API has changed. This makes sense since authentication is implemented in a subsite, and we know subsites have been updated. To fix this, I call liftHandler
outside of runDB
to run database operations in the site's root monad:
authenticate creds = liftHandler $ runDB $ do
I also run an IO computation inside the database computation, so I eliminated one lift:
-- Original
now <- lift $ lift getCurrentTime
-- Fixed
now <- lift getCurrentTime
When attempting to compile again, I received the following error:
src/Foundation.hs:160:23: error:
• Could not deduce: m ~ (->) a0
from the context: (MonadHandler m, HandlerSite m ~ App)
bound by the type signature for:
authHttpManager :: forall (m :: * -> *).
(MonadHandler m, HandlerSite m ~ App) =>
m Manager
at src/Foundation.hs:160:5-19
‘m’ is a rigid type variable bound by
the type signature for:
authHttpManager :: forall (m :: * -> *).
(MonadHandler m, HandlerSite m ~ App) =>
m Manager
at src/Foundation.hs:160:5-19
Expected type: m Manager
Actual type: a0 -> Manager
• In the expression: getHttpManager
In an equation for ‘authHttpManager’:
authHttpManager = getHttpManager
In the instance declaration for ‘YesodAuth App’
• Relevant bindings include
authHttpManager :: m Manager (bound at src/Foundation.hs:160:5)
|
160 | authHttpManager = getHttpManager
| ^^^^^^^^^^^^^^
It looks like some part of the HTTP manager API changed. authHttpManager
has a default implementation though, so I just commented it out. You may need to implement this if you are not using the default global manager.
The following is the last error I encountered:
app/DevelMain.hs:40:1: error:
Could not find module ‘Foreign.Store’
Perhaps you meant
Foreign.Ptr (from base-4.11.1.0)
Foreign.Safe (from base-4.11.1.0)
Foreign.Storable (from base-4.11.1.0)
Use -v to see a list of the files searched for.
|
40 | import Foreign.Store
| ^^^^^^^^^^^^^^^^^^^^
Module Foreign.Store
is in a separate package now, so I added its package, foreign-store
to my cabal file.
Once I knew what to do, upgrading was relatively painless. If you would like to learn more about the changes in Yesod 1.6, check out Michael Snoyman's blog post.