2015-04-10 3 views
1

Всего здесь нет. Я видел пример выполнения запроса HTTP Get с использованием блока do, но я хочу сделать это с помощью композиции.Функциональная композиция и аннотации типов в Haskell

Как это:

get url = getResponseBody . simpleHTTP $ getRequest url 

Прилично? И какова правильная аннотация для этой функции?

Это один нормально:

get :: String -> IO String 
get url = getResponseBody =<< simpleHTTP (getRequest url) 

Но я хочу, чтобы создавать и не связывать. Что это лучше/правильно?

+0

Можете ли вы предоставить типы для 'getResponseBody',' simpleHTTP' и 'getRequest'? Или, по крайней мере, модуль (ы), из которого они берутся? – bheklilr

+0

Они происходят из Network.HTTP – Roman

+0

Что случилось с привязкой? '= <<' _is_, в некотором смысле, композиция для монадических функций (также называемых стрелками Клейсли). Точнее, '<= <' - оператор композиции Клейсли: 'get = getResponseBody <= leftaroundabout

ответ

5

Если мы посмотрим на типы:

getRequest :: String -> Request_String 
simpleHTTP :: Request ty -> IO (Result (Response ty)) 
getResponseBody :: Result (Response ty) -> IO ty 
type Request_String = Request String 

Таким образом, для целей данного вопроса мы можем специализироваться типы для

simpleHTTP :: Request_String -> IO (Result (Response String)) 
getResponseBody :: Result (Response String) -> IO String 

довольно ясно видеть, что мы можем просто сделать

simpleHTTP (getRequest url) :: IO (Result (Response String)) 

Однако, чтобы составить это с помощью getResponseBody, мы должны использовать monadic combi nators. Для этого существуют всевозможные математические причины, но для простоты просто подумайте об этом, поскольку состав функций не достаточно мощный, чтобы составлять действия вместе, а только функции. Для составления действий были введены монады, и вместо этого они пришли со своими собственными операторами композиции. Сравните типы этих двух составных операторов:

(.) ::   (b -> c) -> (a -> b) -> (a -> c) 
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> (a -> m c) -- Imported from Control.Monad 

Они очень похожи, не так ли? Единственная разница заключается в добавлении m с ограничением Monad. Это оператор композиции для монад, он более ограничительный и мощный, чем обычный оператор ., что означает, что он может выполнять больше, например, последовательность и выполнение операций ввода-вывода, но это также означает, что он работает с меньшим количеством типов. Он может быть использован в качестве

get = simpleHTTP <=< simpleHTTP . getRequest 

Однако, есть более обобщенный вариант композиции определяется в Control.Category, который может обрабатывать как:

import Prelude hiding ((.), id) -- Hide the less general versions in Prelude 
import Control.Category 
import Control.Arrow 

get = runKleisli (Kleisli getResponseBody . Kleisli simpleHTTP) . getRequest 

Но это требует, чтобы вы обернуть монадических функции в Kleisli Newtype обертки и разверните его с помощью runKleisli. Вы также можете пропустить Control.Category и просто использовать Control.Arrow:

get = runKleisli (Kleisli getResponseBody <<< Kleisli simpleHTTP) <<< getRequest 

Вы даже можете поменять это вокруг, чтобы быть

get = getRequest >>> runKleisli (Kleisli simpleHTTP >>> Kleisli getResponseBody) 

, если вы хотите, чтобы читать слева направо, а не справа налево ,

В конце концов, существует несколько способов написания эквивалентного кода, но наиболее знакомый и читаемый большинству людей, если вы непреклоняетесь по беспроблемному стилю (необязательно быть идиоматическим), было бы использовать обычно . и <=<, поскольку это кратчайшая реализация и использует более узнаваемые операторы.Control.Category и Control.Arrow очень полезны при создании чего-то пользовательского, но для встроенных типов обычно уже определены определенные операторы, которые имеют больше смысла.

+0

Спасибо! Поэтому '>> =' - это оператор компоновки для монадических функций. Есть ли хорошие примеры создания монад? Из того, что я видел: монада описывает набор правил, которым должен следовать тип. И мне кажется, что Монада больше похожа на шаблон дизайна. – Roman

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