Какой прикладной функтор используется для передачи общих параметров?

Я думаю, что я понимаю, как аппликативные функторы работают в Haskell, и я использую их для базовых типов данных (возможно, Либо...). Тем не менее, я нашел этот вопрос в следующем примере:

withPool pool = bracket (takeConn pool) (putConn pool)

можно переписать в аппликативном стиле:

withPool = bracket <$> takeConn <*> putConn

Я был удивлен, что он скомпилирован и действительно работает так, как ожидалось, но может ли кто-нибудь сказать мне, какой Аппликативный Functor используется для этого и как он определяется?

Обновление: я думаю, что я понял, как это работает, но я понятия не имею, где это определено.

Ответы

Ответ 1

Унифицировать f= (a ->) в типе подписей:

fmap :: (b -> c) -> (a -> b) -> (a -> c)
pure :: b -> (a -> b)
(<*>) :: (a -> b -> c) -> (a -> b) -> (a -> c)

Единственная причина, по которой объявления синтаксически различны, ((->) a) vs (a ->), заключается в том, что вам не разрешено принимать разделы на уровне типа. Таким образом, вы в конечном итоге с ними, после чеканки типов:

instance Functor ((->) a) where
    fmap = (.)

instance Applicative ((->) a) where
    pure = const
    f <*> g = \x -> f x $ g x

Я уверен, что экземпляр Functor находится в Data.Functor, а экземпляр Applicative находится в Control.Applicative. Экземпляр Monad для ((->) a) является единственным в странном месте в Control.Monad.Instances вместо Control.Monad. По крайней мере, если я правильно помню.