Tüm tasarımlar üç ana kaygıları ile tahrik gibi görünüyor:
- talepler organları (böylece biz değil akışa sahip olabilir bunları işlemeye başlamadan önce hepsini bellekte yüklemelisiniz). En iyi nasıl temsil edilir?
- Yanıtlar da yayınlanabilir. En iyi nasıl temsil edilir?
- Bir yanıtın üretimine ayrılan kaynakların uygun şekilde nasıl serbest bırakıldığından emin olunur? (Örneğin, emin olmak için nasıl dosya kolları? Bir dosya yattıktan sonra serbest bırakılan)
type Application = Request -> Iteratee B.ByteString IO Response
This version Haskell akış verileri için erken çözüm olduğunu iteratees kullanır. Yinelemeli tüketiciler, modern akan kütüphanelerde kullanılan “çekmeye dayalı” tüketicilerden daha az doğal olan “basma temelli” bir şekilde yazılmalıydı.
İsteğin akış halindeki gövdesi yinelemeye beslenir ve sonunda bir Response
değeri alırız. Response
, bir numaralandırıcı (sunucu tarafından sağlanan yanıt yinelemesine iletilen yanıt baytlarını besleyen bir işlev) içerir. Muhtemelen sayımcı, bracket
gibi işlevleri kullanarak kaynak tahsisini kontrol edecektir.
type Application = Request -> ResourceT IO Response
This version
yerine sýralayýcý bunu yapmanın, kaynak yönetimi için
resourcet monad trafo kullanır. Aktarılan veriyi işleyen (ve IMHO için biraz zor olan) hem de
Request
ve
Response
içinde özel bir
Source
türü vardır.
type Application = Request -> IO Response
Bu sürüm conduit gelen akış soyutlamalar kullanır, ancak resourcet kaçınan ve bunun yerine akış yanıtlarda kaynaklarını işlemek için bir braket benzeri responseSourceBracket
fonksiyonunu sağlar. Kaynak tahsisi kontrol etmek için düzenli olarak bracket
benzeri işlevleri kullanmak için işleyici çalışmasını sağlayan bir devamı tabanlı yaklaşım
type Application = Request -> (forall b. (Response -> IO b) -> IO b)
type Application = Request -> (Response -> IO ResponseReceived) -> IO ResponseReceived
This version hareket eder. Bu açıdan, bire dönüş!
Akışlar artık akış için kullanılmamaktadır.Şimdi, istek akışının parçalarını okumak için Request -> IO ByteString
function ve yanıt akışını oluşturmak için Response
'da (Builder -> IO()) -> IO() -> IO()
function bulunmaktadır. (Builder -> IO()
yazma işlevi, bir yıkama eylemi ile birlikte sunucu tarafından sağlanır.)
Yeniden oluşturmaya dayalı sürümler gibi ve yinelemeye dayalı sürümden farklı olarak, bu uygulama yanıt akışını gerçekleştirerek istek gövdesinin okunmasını sağlar. işleyici bir b
dönmek gerekiyor ve bir tane almak için tek yol aslında geri arama çağırmaktır:
polimorfik işleyicisi yanıtı alma geri arama Response -> IO b
hep çağrılmasını sağlamak için düzgün bir hile!
Bu polimorfik çözüm bazı sorunlara yol açmış gibi görünüyor (belki de kapsayıcılarda işleyicileri depolamakla birlikte). Polimorfizm kullanmak yerine, ortak kurucu olmadan ResponseReceived
belirtecini kullanabiliriz. Efekt aynıdır: İşleyici kodunun geri dönmesi gereken belirteci tutması için tek yol geri çağırma işlemini çağırmaktır.
Yeniden tasarlamanın ardındaki * kuvvetin * haklı çıkma arzusu olduğunu öne sürmek isterim. – Carl