【问题标题】:Couldn't match expected type `HandlerT...' with actual type `IO String'无法将预期类型“HandlerT...”与实际类型“IO String”匹配
【发布时间】:2017-01-18 09:40:12
【问题描述】:

尝试制作一个 yesod 应用程序(没有堆栈和yesod init),当我编译它时,我遇到了这个 monad 错误。我知道这些问题很常见,但我从未见过有人用这些特定类型(即 HandlerT 和 IO 字符串)提出这个问题。这是我所有的代码,所以我认为有人测试它应该很容易。另外我使用的是 GHC 7.10.3,它有点旧,但我认为我的问题与编译器版本无关。

$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.10.3

这是编译器错误消息:

$ ghc -o yesod_test yesod_monad_test.hs
[1 of 1] Compiling Main             ( yesod_monad_test.hs, yesod_monad_test.o )

yesod_monad_test.hs:25:15:
    Couldn't match expected type `HandlerT HelloWorld IO Text'
                with actual type `IO String'
    In a stmt of a 'do' block: snippet <- readFile temp
    In the expression:
      do { let temp = "posts/" ++ title ++ ".html";
           snippet <- readFile temp;
           defaultLayout
             ((asWidgetT . toWidget) (toHtml (preEscapedText snippet))) }

这是我的代码。

{-# LANGUAGE OverloadedStrings     #-}
{-# LANGUAGE QuasiQuotes           #-}
{-# LANGUAGE TemplateHaskell       #-}
{-# LANGUAGE TypeFamilies          #-}
{-# LANGUAGE ViewPatterns          #-}

import Yesod
import Network.Wai           (pathInfo, rawPathInfo, requestMethod, responseLBS)
import Data.Text             (Text)
import Text.Blaze            (preEscapedText)
import Control.Exception     (IOException, try)
import Control.Monad         (when)

data HelloWorld = HelloWorld

mkYesod "HelloWorld" [parseRoutes|
 /post/#String PostR GET
|]

instance Yesod HelloWorld

getPostR :: String -> Handler Html
getPostR title = do
   let temp = "posts/" ++ title ++ ".html"
   snippet <- readFile temp
   defaultLayout [whamlet|#{preEscapedText snippet}|]

main :: IO ()
main = warp 3000 HelloWorld

我很惊讶这段代码不起作用,因为我相信我非常密切地遵循教程 (http://www.yesodweb.com/book/routing-and-handlers#routing-and-handlers_overlap_checking),尽管我在 Text 类型上使用字符串。

谢谢。

【问题讨论】:

  • 你正试图在一个 do 块内为一个不是 IO 单子 (Handler Html) 的单子执行 IO (readFile)。我不知道 Handler 类型同义词的详细信息,但 IO 存在于其定义中的事实表明它将支持某些操作,例如 liftIO,您可以使用它来将 IO 操作提升到适当的地点。
  • 基本上,@amalloy 告诉您将 snippet &lt;- readFile temp 替换为 snippet &lt;- liftIO $ readFile temp

标签: haskell yesod


【解决方案1】:

@Alec 的回答基本上是正确的。谢谢!

基本上,@amalloy 告诉您将 snippet &lt;- readFile temp 替换为 snippet &lt;- liftIO $ readFile temp

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-03-02
    • 2017-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多