Я читаю главу 25 (Составление типов) из haskellbook и хочу более полно понять аппликативную композицию
Автор предоставляет тип для воплощения композиции типов:
newtype Compose f g a =
Compose { getCompose :: f (g a) }
deriving (Eq, Show)
и предоставляет экземпляр функтора для этого типа:
instance (Functor f, Functor g) =>
Functor (Compose f g) where
fmap f (Compose fga) =
Compose $ (fmap . fmap) f fga
Но экземпляр Applicative оставлен читателю в качестве упражнения:
instance (Applicative f, Applicative g) =>
Applicative (Compose f g) where
-- pure :: a -> Compose f g a
pure = Compose . pure . pure
-- (<*>) :: Compose f g (a -> b)
-- -> Compose f g a
-- -> Compose f g b
Compose fgf <*> Compose fgx = undefined
Я могу обманутьи найдите ответ в Интернете ... Источник Data.Functor.Compose предоставляет определение аппликативного экземпляра:
Compose f <*> Compose x = Compose ((<*>) <$> f <*> x)
, но у меня возникают проблемы с пониманием того, что здесь происходит.Согласно сигнатурам типа f
и x
заключены в два слоя аппликативной структуры.Дорожный блок, на который я, кажется, нахожусь, хотя понимает, что происходит с этим битом: (<*>) <$> f
.У меня, вероятно, будут дополнительные вопросы, но они, вероятно, зависят от того, как оценивается это выражение.Это говорит «fmap <*>
over f» или «применить <$>
к f»?
Пожалуйста, помогите прийти к интуитивному пониманию того, что здесь происходит.
Спасибо!:)