Попытка сделать приложение yesod (без стека и yesod init
), и когда когда-либо я его скомпилирую, я сталкиваюсь с этой ошибкой монады. Я знаю, что эти проблемы распространены, но я никогда не видел, чтобы кто-нибудь задавал этот вопрос с этими конкретными типами (например, HandlerT и IO String). Вот мой код, поэтому я считаю, что это должно быть достаточно легко, чтобы кто-то мог это проверить. Также я использую GHC 7.10.3, который немного старше, но я не думаю, что моя проблема имеет какое-либо отношение к версии компилятора.Не удалось совместить ожидаемый тип `HandlerT ... 'с фактическим типом` IO String'
$ 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) довольно близко, хотя я использую струны над типом текста.
спасибо.
Вы пытаетесь выполнить IO ('readFile') внутри блока do для монады, которая не является монадой ввода-вывода (' Handler Html'). Я не знаю деталей синонима типа «Handler», но тот факт, что IO присутствует в его определении, предполагает, что он поддержит некоторую операцию, такую как «liftIO», которую вы могли бы использовать для подъема операции ввода-вывода до надлежащего место. – amalloy
В основном, @amalloy говорит вам заменить «snippet <- readFile temp» на 'snippet <- liftIO $ readFile temp'. – Alec