Happstack отображает прочитанный файл

Это новый вопрос Haskell, вероятно, связанный с монадой IO().

У меня есть функция в программе Happstack.Server, которая генерирует ответ на загрузку файла.

postFile = do methodM POST
              decodeBody filePolicy
              (tmp, name, meta) <- lookFile "upload"
              ok $ concat ["A file! ", tmp, " || ", name, " || ", show meta]

Это прекрасно работает. Теперь я хотел бы, чтобы он отображал содержимое загруженного файла, а также его локальное временное имя, исходное имя и метаданные типа содержимого. Я предполагал, что, поскольку все это происходит в блоке do, я мог бы просто

postFile = do methodM POST
              decodeBody filePolicy
              (tmp, name, meta) <- lookFile "upload"
              contents <- readFile tmp
              ok $ concat ["A file! ", tmp, " || ", name, " || ", show meta, "\n\n", contents]

но это дает мне ряд ошибок, которые, кажется, говорят мне, что что-то не так с вызовом decodeBody.

...
/home/inaimathi/projects/happstack-tutorial/parameters.hs:23:15:
    No instance for (Happstack.Server.Internal.Monads.WebMonad
                       Response IO)
      arising from a use of `decodeBody'
    Possible fix:
      add an instance declaration for
      (Happstack.Server.Internal.Monads.WebMonad Response IO)
    In a stmt of a 'do' block: decodeBody filePolicy
    In the expression:
      do { methodM POST;
           decodeBody filePolicy;
           (tmp, name, meta) <- lookFile "upload";
           contents <- readFile tmp;
           .... }
    In an equation for `postFile':
        postFile
          = do { methodM POST;
                 decodeBody filePolicy;
                 (tmp, name, meta) <- lookFile "upload";
                 .... }
...

Я не уверен, что здесь происходит не так. Может ли кто-нибудь просветить меня?


EDIT3:

Это научит меня делать поспешные выводы.

Все дополнительные ошибки, которые я получал, были связаны с неправильно установленными библиотеками. Очистка моего ~/.ghc, а затем установка happstack снова исправили это.


person Inaimathi    schedule 02.11.2012    source источник
comment
Не знаю Happstack, но вам, вероятно, нужно использовать liftIO $ readFile tmp.`   -  person hammar    schedule 02.11.2012
comment
Как уже говорили другие, вам просто нужно «liftIO». Я добавлю раздел в Ускоренный курс по этому вопросу.   -  person stepcut    schedule 02.11.2012


Ответы (1)


No instance for (Happstack.Server.Internal.Monads.WebMonad
                       Response IO)

Перевод: ваш do-блок - это не монада IO, а какая-то другая монада. К счастью, это экземпляр MonadIO:

class Monad m => MonadIO m where
    liftIO :: IO a -> m a

Как видите, такой экземпляр просто предоставляет способ «поднять» действия ввода-вывода из монады ввода-вывода в себя, поэтому в вашем случае вам просто нужно:

contents <- liftIO $ readFile tmp

Реализация liftIO, очевидно, зависит от m, но в типичном стеке преобразования монад он использует lift и liftIO для доступа к монаде IO внутри; см., например, реализации для другие преобразователи монад в библиотеке Transformers.

person Fixnum    schedule 02.11.2012
comment
Добавлено редактирование вопроса после того, как вы попробовали это предложение; кажется, это не так просто, как добавить liftIO. - person Inaimathi; 02.11.2012
comment
Happstack.Server.Internal.Monads.ServerPartT IO String (:t в ghci отчетах Happstack.Server.Internal.Monads.ServerPartT IO [Char]) - person Inaimathi; 03.11.2012
comment
Я не могу воспроизвести проблему No instance for (Control.Monad.IO.Class.MonadIO (Happstack.Server.Internal.Monads.ServerPartT IO)). Конечно, компилятор должен иметь возможность вывести этот экземпляр из объявлений в Happstack.Server.Internal.Monads и Control.Monad.IO.Class, поэтому я запутался. - person Fixnum; 03.11.2012
comment
Косметическое предложение - внутренние модули не предназначены для использования в приложениях, поэтому вы можете вместо этого присвоить postFile тип ServerPart String. - person Fixnum; 03.11.2012
comment
Добавлено объявление типа postFile :: ServerPart String, просто чтобы сделать его явным. Версия без readFile по-прежнему работает нормально, но добавление дополнительного присваивания к contents выдает ту же ошибку. - person Inaimathi; 03.11.2012
comment
Из любопытства, использовали ли вы какие-либо языковые прагмы, когда пытались воспроизвести это? - person Inaimathi; 03.11.2012
comment
Хм. Похоже, что последняя ошибка является результатом архитектуры моей машины (ваше предложение отлично работает на 32-битной машине, но, как я заметил выше, на 64-битной, все еще не работает). - person Inaimathi; 03.11.2012