简体   繁体   English

Yesod中模板haskell的评估

[英]Evaluation of template haskell in Yesod

While going through the examples of the Yesod Book, I'm running into an issue with the following snippet:在浏览 Yesod Book 的示例时,我遇到了以下代码段的问题:

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes       #-}
{-# LANGUAGE TemplateHaskell   #-}
{-# LANGUAGE TypeFamilies      #-}
{-# LANGUAGE ViewPatterns      #-}
import           Data.Text (Text)
import qualified Data.Text as T
import           Yesod

data App = App
instance Yesod App

mkYesod "App" [parseRoutes|
/person/#Text PersonR GET
/year/#Integer/month/#Text/day/#Int DateR
/wiki/*Texts WikiR GET
|]

getPersonR :: Text -> Handler Html
getPersonR name = defaultLayout [whamlet|<h1>Hello #{name}!|]

handleDateR :: Integer -> Text -> Int -> Handler Text -- text/plain
handleDateR year month day =
    return $
        T.concat [month, " ", T.pack $ show day, ", ", T.pack $ show year]

getWikiR :: [Text] -> Handler Text
getWikiR = return . T.unwords

main :: IO ()
main = warp 3000 App

(It's on page 124 of 598; route arguments ) (在 598 页的第 124 页; 路线 arguments

The instance declaration on line 11 raises the following error:第 11 行的实例声明引发以下错误:

YesodRouteParams.hs:11:10: error:
    • No instance for (RenderRoute App)
        arising from the superclasses of an instance declaration
    • In the instance declaration for ‘Yesod App’
   |
11 | instance Yesod App
   |

It can be fixed by moving that line below the mkYesod block, where routes are defined.可以通过将该行移动到定义路由的mkYesod块下方来修复它。

I'm trying to understand why that is.我试图理解为什么会这样。 Does it mean that Template Haskell evaluation at compile time happens simultaneously with the written code evaluation?这是否意味着在编译时模板 Haskell 评估与书面代码评估同时发生?

I ask because in Crystal, for example, macros are expanded before anything else.我问是因为在水晶中,例如,宏在其他任何东西之前都会被扩展。 So the order of things doesn't really matter in a file (or app).因此,文件(或应用程序)中的事情顺序并不重要。 But by the looks of it, they do in Haskell.但从表面上看,他们确实在 Haskell 中。 Or is there another explanation?还是有其他解释?

This was because of a change made in GHC 9.0.1.这是因为在 GHC 9.0.1 中进行了更改。 From the release notes :发行说明

Breaking change: Template Haskell splices now act as separation points between constraint solving passes.重大更改:模板 Haskell 接头现在充当约束求解通道之间的分离点。 It is no longer possible to use an instance of a class before a splice and define that instance after a splice.不再可能在拼接之前使用 class 的实例并在拼接之后定义该实例。 For example, this code now reports a missing instance for C Bool :例如,此代码现在报告C Bool的缺失实例:

 class C a where foo:: a bar:: Bool bar = foo $(return []) instance C Bool where foo = True

If you were to downgrade to GHC 8.10.7, you'd see that your code would then work as you wrote it.如果您要降级到 GHC 8.10.7,您会看到您的代码将按照您编写的方式运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM