13

我浏览了 yesod 的书和源代码,并了解了一切是如何运作的。但在我写自己的东西之前,在脚手架站点中有一件事我只是不明白。

所以我搭建了一个站点“copywww”,在文件 CopyWWWState.hs 中有代码:

instance YesodPersist CopyWWWState where
    type YesodDB CopyWWWState = SqlPersist
    runDB db = liftIOHandler
             $ fmap connPool getYesod >>= Settings.runConnectionPool db

instance YesodAuth CopyWWWState where
    type AuthId CopyWWWState = UserId

    -- Where to send a user after successful login
    loginDest _ = RootR
    -- Where to send a user after logout
    logoutDest _ = RootR

    getAuthId creds = runDB $ do
        x <- getBy $ UniqueUser $ credsIdent creds
        case x of
            Just (uid, _) -> return $ Just uid
            Nothing -> do
                fmap Just $ insert $ User (credsIdent creds) Nothing

    authPlugins = [ authOpenId
                  , authEmail
                  ]

我不明白的行是:

type AuthId CopyWWWState = UserId
type YesodDB CopyWWWState = SqlPersist

当我删除它们时,显然会出现错误,但我不确定为什么首先需要它们。当我搜索“UserId”或“SqlPersist”的来源时,我没有找到任何看起来有希望的东西。这段代码到底需要做什么?yesod 在这些类中使用类型族有什么好处?

4

2 回答 2

7

脚手架上有很多事情可能不会立即显而易见。在 config/model 中,有一个持久实体定义如下:

User
  name String
  foo String

这将创建一个 User 类型,它是 PersistEntity 的一个实例,以及一个 UserId 类型,它的用途如下:

instance PersistEntity User where
  ...
  Key User = UserId

脚手架放入的原因:

type AuthId CopyWWWState = UserId

只是用户是一个逻辑参考点。现在,在您的代码中,无论何时调用,requireAuth您都会得到类似的东西Handler User,并且requireAuthId会给您一个Handler UserId相当于Handler (Key User). 您可以随意将这些更改为您想要的任何内容,但您必须更改 YesodAuth 类型类实例中的一些其他函数。

希望这可以帮助。是的岩石。需要一两个星期才能感觉到它是如何粘在一起的,但是当你做这样的事情时,它是非常强大的。

于 2011-06-08T11:29:18.137 回答
2

类型族类似于功能依赖项。它们都提供了一种在多个参数上抽象类型类的方法,同时保持类型检查器满意。本地type只是意味着您有一个受实例绑定的额外参数。这意味着,实例可以自行决定在该位置使用哪种类型。实例也可以使用更通用的类型而不是特定的类型来给用户选择。在您的情况下,您可能依赖于 ypur 数据库类型YesodDB实际上是 SQL 数据库 ( SqlPersist) 的事实。所以需要这些信息来满足类型检查器的要求。

于 2011-06-07T19:37:26.243 回答