Могу ли я написать более высокий тип заказа для a → b → *?

Я понимаю, что (->) a является типом более высокого порядка * -> *, который при применении к аргументу типа b дает тип a -> b

Можно ли написать тип вида * -> *, который при применении к c дал бы a -> b -> c?

Если нет, почему бы и нет? Возможно, используя некоторые расширения языка и forall?

Это позволило бы мне написать экземпляры Functor и Applicative (и других классов), где функториальная структура "a -> b ->", как в:

(<*>) :: Applicative t => t (c -> d) -> t c -> t d

(<*>) :: (a -> b -> c -> d) -> (a -> b -> c) -> a -> b -> d

Это было бы полезно в качестве комбинатора для двоичных (curried) функций.

NB. Возможно, это связано с Функторами и Применениями для типов вида (* → *) → *, но я не уверен, потому что это пошло мне на голову: -)

Ответ 1

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

instance Functor (\c. a -> b -> c) where ...

К сожалению, лямбды уровня типа означают, что мы должны перейти от объединения первого порядка к объединению высшего порядка во время вывода типа, что особенно сложно. (Я хочу сказать, что можно сказать, что я не могу сказать, но я не уверен в этом.)

Вы можете получить на полпути, если вы вставляете явный запрос проверки типов с помощью оболочки newtype. Стандартный Compose:

a -> b -> c ~= Compose (a ->) (b ->) c
\c. a -> b -> c ~= Compose (a ->) (b ->)

И действительно, экземпляры Functor и Applicative для Compose (a ->) (b ->) - это именно те, которые вы ожидаете для \c. a -> b -> c, ценой небольшого синтаксического шума при создании и потреблении значений этого типа.