yesod-core: Make it work with ghc-8.0

Use CPP hackery to make it compile with ghc-8.0 and ghc 7.10. If
ghc-7.10 works, I assume earlier supported versions of GHC also
work. All tests pass with both GHC versions.

Unfortunately, the TH changes force changes in the type signature
of Yesod.Routes.TH.RenderRoute.mkRouteCons from:

    mkRouteCons :: [ResourceTree Type] -> ([Con], [Dec])

to

    mkRouteCons :: [ResourceTree Type] -> Q ([Con], [Dec])

and I can't see a way around that.
This commit is contained in:
Erik de Castro Lopo 2016-04-15 11:50:06 +10:00
parent 1b5477bc78
commit 226c381baa
3 changed files with 39 additions and 13 deletions

View File

@ -86,8 +86,13 @@ mkYesodGeneral namestr args isSub f resS = do
case info of
TyConI dec ->
case dec of
#if MIN_VERSION_template_haskell(2,11,0)
DataD _ _ vs _ _ _ -> length vs
NewtypeD _ _ vs _ _ _ -> length vs
#else
DataD _ _ vs _ _ -> length vs
NewtypeD _ _ vs _ _ -> length vs
#endif
_ -> 0
_ -> 0
_ -> return 0

View File

@ -8,6 +8,9 @@ module Yesod.Routes.TH.RenderRoute
) where
import Yesod.Routes.TH.Types
#if MIN_VERSION_template_haskell(2,11,0)
import Language.Haskell.TH (conT)
#endif
import Language.Haskell.TH.Syntax
import Data.Maybe (maybeToList)
import Control.Monad (replicateM)
@ -19,15 +22,15 @@ import Data.Monoid (mconcat)
#endif
-- | Generate the constructors of a route data type.
mkRouteCons :: [ResourceTree Type] -> ([Con], [Dec])
mkRouteCons =
mconcat . map mkRouteCon
mkRouteCons :: [ResourceTree Type] -> Q ([Con], [Dec])
mkRouteCons rttypes =
mconcat <$> mapM mkRouteCon rttypes
where
mkRouteCon (ResourceLeaf res) =
([con], [])
return ([con], [])
where
con = NormalC (mkName $ resourceName res)
$ map (\x -> (NotStrict, x))
$ map (\x -> (notStrict, x))
$ concat [singles, multi, sub]
singles = concatMap toSingle $ resourcePieces res
toSingle Static{} = []
@ -39,14 +42,19 @@ mkRouteCons =
case resourceDispatch res of
Subsite { subsiteType = typ } -> [ConT ''Route `AppT` typ]
_ -> []
mkRouteCon (ResourceParent name _check pieces children) =
([con], dec : decs)
mkRouteCon (ResourceParent name _check pieces children) = do
(cons, decs) <- mkRouteCons children
#if MIN_VERSION_template_haskell(2,11,0)
dec <- DataD [] (mkName name) [] Nothing cons <$> mapM conT [''Show, ''Read, ''Eq]
#else
let dec = DataD [] (mkName name) [] cons [''Show, ''Read, ''Eq]
#endif
return ([con], dec : decs)
where
(cons, decs) = mkRouteCons children
con = NormalC (mkName name)
$ map (\x -> (NotStrict, x))
$ map (\x -> (notStrict, x))
$ concat [singles, [ConT $ mkName name]]
dec = DataD [] (mkName name) [] cons [''Show, ''Read, ''Eq]
singles = concatMap toSingle pieces
toSingle Static{} = []
@ -143,10 +151,23 @@ mkRenderRouteInstance = mkRenderRouteInstance' []
mkRenderRouteInstance' :: Cxt -> Type -> [ResourceTree Type] -> Q [Dec]
mkRenderRouteInstance' cxt typ ress = do
cls <- mkRenderRouteClauses ress
let (cons, decs) = mkRouteCons ress
(cons, decs) <- mkRouteCons ress
#if MIN_VERSION_template_haskell(2,11,0)
did <- DataInstD [] ''Route [typ] Nothing cons <$> mapM conT clazzes
#else
let did = DataInstD [] ''Route [typ] cons clazzes
#endif
return $ InstanceD cxt (ConT ''RenderRoute `AppT` typ)
[ DataInstD [] ''Route [typ] cons clazzes
[ did
, FunD (mkName "renderRoute") cls
] : decs
where
clazzes = [''Show, ''Eq, ''Read]
#if MIN_VERSION_template_haskell(2,11,0)
notStrict :: Bang
notStrict = Bang NoSourceUnpackedness NoSourceStrictness
#else
notStrict :: Strict
notStrict = NotStrict
#endif

View File

@ -41,7 +41,7 @@ case500 :: IO ()
case500 = runner $ do
res <- request defaultRequest
assertStatus 500 res
assertBody "FOOBAR" res
assertBodyContains "FOOBAR" res
caseRedirect :: IO ()
caseRedirect = runner $ do