Given the following definitions:
import Control.Monad.ST import Data.STRef fourty_two = do x <- newSTRef (42::Int) readSTRef x
The following compiles under GHC:
main = (print . runST) fourty_two -- (1)
But this does not:
main = (print . runST) $ fourty_two -- (2)
But then as bdonlan points out in a comment, this does compile:
main = ((print . runST) $) fourty_two -- (3)
But, this does not compile
main = (($) (print . runST)) fourty_two -- (4)
Which seems to indicate that (3) only compiles due to special treatment of infix
$, however, it still doesn't explain why (1) does compile.
1) I've read the following two questions (first, second), and I've been led to believe
$ can only be instantiated with monomorphic types. But I would similarly assume
. can only be instantiated with monomorphic types, and as a result would similarly fail.
Why does the first code succeed but the second code does not? (e.g. is there a special rule GHC has for the first case that it can't apply in the second?)
2) Is there a current GHC extension that compiles the second code? (perhaps ImpredicativePolymorphism did this at some point, but it seems deprecated, has anything replaced it?)
3) Is there any way to define say
`my_dollar` using GHC extensions to do what
$ does, but is also able to handle polymorphic types, so
(print . runST) `my_dollar` fourty_two compiles?
Edit: Proposed Answer:
Also, the following fails to compile:
main = ((.) print runST) fourty_two -- (5)
This is the same as (1), except not using the infix version of
As a result, it seems GHC has special rules for both
., but only their infix versions.