Yesod 中模板 haskell 的评估

wou*_*out 2 haskell yesod template-haskell

在浏览 Yesod Book 的示例时,我遇到了以下代码片段的问题:

\n
{-# LANGUAGE OverloadedStrings #-}\n{-# LANGUAGE QuasiQuotes       #-}\n{-# LANGUAGE TemplateHaskell   #-}\n{-# LANGUAGE TypeFamilies      #-}\n{-# LANGUAGE ViewPatterns      #-}\nimport           Data.Text (Text)\nimport qualified Data.Text as T\nimport           Yesod\n\ndata App = App\ninstance Yesod App\n\nmkYesod "App" [parseRoutes|\n/person/#Text PersonR GET\n/year/#Integer/month/#Text/day/#Int DateR\n/wiki/*Texts WikiR GET\n|]\n\ngetPersonR :: Text -> Handler Html\ngetPersonR name = defaultLayout [whamlet|<h1>Hello #{name}!|]\n\nhandleDateR :: Integer -> Text -> Int -> Handler Text -- text/plain\nhandleDateR year month day =\n    return $\n        T.concat [month, " ", T.pack $ show day, ", ", T.pack $ show year]\n\ngetWikiR :: [Text] -> Handler Text\ngetWikiR = return . T.unwords\n\nmain :: IO ()\nmain = warp 3000 App\n
Run Code Online (Sandbox Code Playgroud)\n

(位于第 124 页,共 598 页;路由参数

\n

第 11 行的实例声明引发以下错误:

\n
YesodRouteParams.hs:11:10: error:\n    \xe2\x80\xa2 No instance for (RenderRoute App)\n        arising from the superclasses of an instance declaration\n    \xe2\x80\xa2 In the instance declaration for \xe2\x80\x98Yesod App\xe2\x80\x99\n   |\n11 | instance Yesod App\n   |\n
Run Code Online (Sandbox Code Playgroud)\n

可以通过将该线移动到下面来修复它mkYesod定义路线的块下方来修复此问题。

\n

我试图理解这是为什么。这是否意味着编译时的 Template Haskell 评估与编写的代码评估同时发生?

\n

我问这个问题是因为,例如,在 Crystal 中,宏首先会被扩展。因此,文件(或应用程序)中事物的顺序并不重要。但从表面上看,他们在 Haskell 中做到了。或者还有其他解释吗?

\n

Jos*_*ica 5

这是因为 GHC 9.0.1 中进行了更改。从发行说明来看:

重大更改:模板 Haskell 拼接现在充当约束求解过程之间的分离点。不再可能在拼接之前使用类的实例并在拼接之后定义该实例。例如,此代码现在报告缺少以下实例C Bool

class C a where foo :: a
bar :: Bool
bar = foo
$(return [])
instance C Bool where foo = True
Run Code Online (Sandbox Code Playgroud)

如果您要降级到 GHC 8.10.7,您会发现您的代码将按照您编写的方式运行。

我打开https://github.com/yesodweb/yesodweb.com-content/pull/269来修复书中的示例。