Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell's ($) is a magic operator?

Tags:

haskell

Say I have the following functions:

infixr 0 <|

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

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

The following does not type check:

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

However, foo 3 $ id does.

The definition of (<|) is (as far as I know) identical to the definition of ($). I pretty much ripped out the definition from the base library sources, and changed every instance of ($) to (<|). Compiler magic?

like image 262
YellPika Avatar asked Dec 27 '13 06:12

YellPika


1 Answers

Yes, there's a small amount of compiler magic around ($) to handle impredicative types. It was introduced because everyone expects

runST $ do
  foo
  bar
  baz

to typecheck, but it cannot normally. For more details see here (search runST), this email, and this email. The short of it is that there's actually a special rule in the type-checker specifically for ($) which gives it the ability to resolve the common case of impredicative types.

like image 137
J. Abrahamson Avatar answered Sep 19 '22 05:09

J. Abrahamson