2014-09-09 2 views
2

Я использую Control.Monad.Managed обернуть pipes-http«s withHTTP в продолжении трансформатора, но я также хочу, чтобы поток ответа HTTP из впоследствии:потока от `Managed` труб

import Pipes 
import Pipes.ByteString 
import Pipes.HTTP 
import Control.Applicative 
import Control.Monad 
import Control.Monad.Managed 
import qualified Data.ByteString.Char8  as BC 

type RespBody = BC.ByteString 

managedHTTP :: Request -> Manager -> Managed (Response (Producer RespBody IO())) 
managedHTTP r m = managed (withHTTP r m) 

fromHTTP :: Request -> Manager -> Producer RespBody IO() 
fromHTTP request manager = join $ liftIO $ fmap (hoist liftIO) $ with response return 
    where response = responseBody <$> managedHTTP request manager 

Здесь fromHTTP предназначен для потоковой передачи из тела ответа. Если выше запускается с:

main = do 
    request <- parseUrl "http://en.wikipedia.org/" 
    manager <- newManager defaultManagerSettings 
    runEffect $ fromHTTP request manager >-> stdout 

recv: invalid argument (Bad file descriptor) я получаю после первого куска, потому что http-client «s responseClose уже закрыл тело ответа.

Как мне передать потоковые HTTP-ответы с помощью труб, если я хочу открыть интерфейс стиля не with?

Спасибо & извинения, если я серьезно недопонимаю продолжение и трубы.

ответ

1

Ваше определение fromHTTP немного сложно понять, но, очевидно, вам нужно выйти из управляемой среды, прежде чем вы начнете использовать производителя. Нечто подобное могло бы быть ближе к тому, что вы собираетесь:

import Pipes 
import Pipes.ByteString 
import Pipes.HTTP 
import Control.Applicative 
import Control.Monad 
import Control.Monad.Managed 
import qualified Data.ByteString.Char8  as BC 

type RespBody = BC.ByteString 

managedHTTP :: Request -> Manager -> Managed (Response (Producer RespBody IO())) 
managedHTTP r m = managed (withHTTP r m) 

managedManager :: ManagerSettings -> Managed Manager 
managedManager settings = managed (withManager settings) 

main = runManaged $ 
    do request <- liftIO $ parseUrl "http://en.wikipedia.org/" 
    manager <- managedManager defaultManagerSettings 
    producer <- managedHTTP request manager 
    liftIO $ runEffect $ responseBody producer >-> stdout 

или просто ломом определения и записи

main = runManaged $ 
    do request <- liftIO $ parseUrl "http://en.wikipedia.org/" 
    manager <- managed (withManager defaultManagerSettings) 
    producer <- managed (withHTTP request manager) 
    liftIO $ runEffect $ responseBody producer >-> stdout 

Обратите внимание, что вы можете сделать бег продюсера в Managed монады, а также:

main = runManaged $ 
    do request <- liftIO $ parseUrl "http://en.wikipedia.org/" 
    manager <- managed (withManager defaultManagerSettings) 
    producer <- managed (withHTTP request manager) 
    runEffect $ hoist liftIO (responseBody producer) >-> stdout 
+0

Я изначально не хотел, чтобы '' fromHTTP'' был '' Managed (Producer ...) '', потому что у меня есть большой стек трансформатора внутри Producer, и я предполагал, что базовая монада - это IO. Я смог исправить эту проблему с помощью '' Control.Monad.Base'' (создание '' Proxy'' экземпляра '' MonadBase'') – tranma

+0

Это решение работает, если вы можете позволить себе '' fromHTTP'' в «Управляемый» (вместо этого). – tranma

+0

О, я вижу. Это немного раздражает, что Managed настолько ограничен, но я полагаю, это помогает сделать пакет понятным. Существует также возможность непосредственного использования 'Codensity', как описано здесь http://hackage.haskell.org/package/pipes-4.1.2/docs/Pipes-Tutorial.html#g:10 (по другой причине), используя конструктор 'Condensity' как' managed' и 'lowerCodensity' как' runManaged'. Или, может быть, я что-то упустил. – Michael

Смежные вопросы