Подтвердить что ты не робот

Haskell ($) - волшебный оператор?

Скажем, что у меня есть следующие функции:

infixr 0 <|

{-# INLINE (<|) #-}
(<|) :: (a -> b) -> a -> b
f <| x = f x

foo :: a -> (forall b. b -> b) -> a
foo x f = f x

Не проверяется следующее:

ghci> foo 3 <| id

Couldn't match expected type `forall b. b -> b'
            with actual type `a0 -> a0'
In the second argument of `(<|)', namely `id'
In the expression: f 3 <| id
In an equation for `it': it = f 3 <| id

Однако foo 3 $ id делает.

Определение (< |) (насколько мне известно) идентично определению ($). Я в значительной степени сорвал определение из базовых источников библиотеки и изменил каждый экземпляр ($) на (< |). Магия компилятора?

4b9b3361

Ответ 1

Да, есть небольшое количество магии компилятора вокруг ($) для обработки нечистоплотных типов. Это было введено, потому что все ожидают

runST $ do
  foo
  bar
  baz

для typecheck, но это нормально. Подробнее см. здесь (поиск runST), этот email, и этот электронная почта. Короче говоря, на самом деле существует специальное правило в контроле типа специально для ($), что дает ему возможность разрешить общий случай нечистоплотных типов.