2017-01-17 12 views
2

Попытка сделать приложение 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) довольно близко, хотя я использую струны над типом текста.

спасибо.

+2

Вы пытаетесь выполнить IO ('readFile') внутри блока do для монады, которая не является монадой ввода-вывода (' Handler Html'). Я не знаю деталей синонима типа «Handler», но тот факт, что IO присутствует в его определении, предполагает, что он поддержит некоторую операцию, такую ​​как «liftIO», которую вы могли бы использовать для подъема операции ввода-вывода до надлежащего место. – amalloy

+3

В основном, @amalloy говорит вам заменить «snippet <- readFile temp» на 'snippet <- liftIO $ readFile temp'. – Alec

ответ

2

@ Ответ Алека был в основном правильным. Благодаря!

В принципе, @amalloy говорит вам, чтобы заменить snippet <- readFile temp с snippet <- liftIO $ readFile temp.