Учитывая следующие определения:
import Control.Monad.ST
import Data.STRef
fourty_two = do
x <- newSTRef (42::Int)
readSTRef x
Следующие компиляции под GHC:
main = (print . runST) fourty_two -- (1)
Но это не так:
main = (print . runST) $ fourty_two -- (2)
Но тогда, как указывает bdonlan в комментарии, это компилируется:
main = ((print . runST) $) fourty_two -- (3)
Но это не компилирует
main = (($) (print . runST)) fourty_two -- (4)
Который, по-видимому, указывает, что (3) компилируется только из-за специальной обработки инфикса $
, однако он все еще не объясняет, почему (1) компилируется.
Вопросы:
1) Я прочитал следующие два вопроса (первый, второй), и я ' верили, что $
может быть введено только с мономорфными типами. Но я бы предположил, что .
может быть создан только с мономорфными типами, и в результате аналогичным образом потерпит неудачу.
Почему первый код преуспевает, а второй - нет? (например, существует ли специальное правило GHC для первого случая, что оно не может применяться во втором?)
2) Существует ли текущее расширение GHC, которое компилирует второй код? (возможно, ImpredicativePolymorphism сделал это в какой-то момент, но, похоже, он устарел, что-нибудь заменило его?)
3) Есть ли способ определить say `my_dollar`
с помощью расширений GHC, чтобы делать то, что делает $
, но также способен обрабатывать полиморфные типы, поэтому (print . runST) `my_dollar` fourty_two
компилирует?
Изменить: Предлагаемый ответ:
Кроме того, следующее не удается скомпилировать:
main = ((.) print runST) fourty_two -- (5)
Это то же самое, что и (1), за исключением использования версии infix .
.
В результате кажется, что GHC имеет специальные правила для $
и .
, но только для своих инфиксных версий.