denormal
denormal

Reputation: 273

Equivalence between '.' and '$'

I have an expression:

gcastWith p1 $
gcastWith p2 $
e

That works ok. Now I am trying to rewrite it as:

((gcastWith p1) .
 (gcastWith p2)) $
e

And it doesn't work (doesn't typecheck). However this works:

((gcastWith p1) .
 (gcastWith p2)) -- note I removed the dollar
e

Am I missing something obvious about how $ and . operate?

Upvotes: 3

Views: 102

Answers (1)

chi
chi

Reputation: 116174

I guess it's some restrictions caused by how type inference works. In basic Hindley-Milner types like

f :: (forall a. G a) -> T

are forbidden. GHC Haskell allows them (with suitable extensions turned on), but still uses the HM restriction requiring that a type variable can never be instantiated to a polytype.

This causes some surprise: f e type checks but f $ e fails since the type variables in the type of $ should be instantiated to a polytype.

e :: forall a. G a
f :: (forall a. G a) -> T
f e :: T

($) :: (b -> c) -> b -> c

Type checking ($) f e:

       b ~ (forall a. G a)   -- forbidden polytype!
       c ~ T

Since f $ e is very common in Haskell, and we really want things like runST $ do .... to work, the GHC devs have added a special-case typing rule for $. Essentially, when fully applied, f $ e is typed like f e.

There is no such special case in the typing system for f . g . h $ e at the moment. This can make it fail when f $ g $ h $ e works fine.

Upvotes: 7

Related Questions