为什么这段代码适用于Yesod.Persist的get404而不是getBy404?

时间:2012-12-10 00:14:44

标签: haskell yesod

假设我有一张狗名和品种表如下:

share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persist|
Dog
    name Text
    breed Text
    UniqueDog name
|]

我有以下路线:

mkYesod "DogApp" [parseRoutes|
/ RootR GET
/dog/name/#Text DogNameR GET
/dog/id/#DogId DogIdR GET
|]

我正在尝试创建一个页面,返回狗的品种,并给出它的名字。我可以通过getDogIdR路由使用URL中的Id来做到这一点:

getDogIdR :: DogId -> Handler RepHtml
getDogIdR dogId = do 
    dog <- runDB $ get404 dogId
    defaultLayout $ do
        [whamlet|
<p>
    <b>#{dogName dog}
<p>
    #{dogBreed dog}
|]

但是,如果我尝试使用getDogNameR路由创建相同的页面,

getDogNameR :: Text -> Handler RepHtml
getDogNameR maybeDogName = do 
    dog <- runDB $ getBy404 (UniqueDog maybeDogName)
    defaultLayout $ do
        [whamlet|
<p>
    <b>#{dogName dog}
<p>
    #{dogBreed dog}
|]

我收到以下错误:

dog.hs:73:20:
    Couldn't match type `Entity' with `DogGeneric'
    In the return type of a call of `getBy404'
    In the second argument of `($)', namely
      `getBy404 (UniqueDog maybeDogName)'
    In a stmt of a 'do' block:
      dog <- runDB $ getBy404 (UniqueDog maybeDogName)

dog.hs:73:20:
    Kind incompatibility when matching types:
      backend0 :: (* -> *) -> * -> *
      DogGeneric SqlPersist :: *
    In the return type of a call of `getBy404'
    In the second argument of `($)', namely
      `getBy404 (UniqueDog maybeDogName)'
    In a stmt of a 'do' block:
      dog <- runDB $ getBy404 (UniqueDog maybeDogName)

为什么会失败,我该如何解决?

似乎get404和getBy404函数返回不同的类型。如果我按如下方式更改getDogNameR路由,它运行正常:

getDogNameR :: Text -> Handler RepHtml
getDogNameR maybeDogName = do 
    dog <- runDB $ getBy404 (UniqueDog maybeDogName)
    defaultLayout $ do
        [whamlet|
<p>
    <b>Dog found!
|]

1 个答案:

答案 0 :(得分:4)

  

似乎get404和getBy404函数返回不同的类型。

右。

get404 :: (PersistStore (t m), PersistEntity val, Monad (t m), m ~ GHandler sub master,
           MonadTrans t, PersistMonadBackend (t m) ~ PersistEntityBackend val)
           => Key val -> t m val

getBy404 :: (PersistUnique (t m), PersistEntity val, m ~ GHandler sub master,
             Monad (t m), MonadTrans t, PersistEntityBackend val ~ PersistMonadBackend (t m))
             => Unique val -> t m (Entity val)

因此,getBy404会将您的狗包裹在Entity中,其中您拥有来自get404的纯狗,如果您更换

,您的第二个代码将会有效
<b>#{dogName dog}

<b>#{dogName (entityVal dog)}

,类似于dogBreed,或者更方便的是,如果您解构返回的Entity绑定

Entity{entityVal = dog} <- runDB $ getBy404 ...