Учитывая следующие определения:
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 в комментарии, это делает compile:
main = ((print. runST) $) fourty_two -- (3)
Но это не компилируется
main = (($) (print. runST)) fourty_two -- (4)
Что, по-видимому, указывает на то, что (3 )компилируется только из-за специальной обработки инфикса $
, однако это все еще не объясняет, почему (1 )компилируется.
Вопросы:
1 )Я прочитал следующие два вопроса(первый , второй), и я пришел к выводу, что $
можно только конкретизировать с мономорфными типами. Но я бы также предположил, что .
может быть создан только с мономорфными типами, и в результате он также потерпит неудачу. Почему первый код работает, а второй нет? (напр. есть ли специальное правило GHC для первого случая, которое не может применяться во втором?)
2 )Существует ли текущее расширение GHC, которое компилирует второй код? (возможно, ImpredicativePolymorphism сделал это в какой-то момент, но кажется, что это устарело, есть ли что-нибудь вместо этого?)
3 )Есть ли способ определить, скажем, `my_dollar`
с помощью расширений GHC, чтобы он делал то, что делает $
, но также может обрабатывать полиморфные типы, чтобы (print. runST) `my_dollar` fourty_two
компилировался?
Редактировать :Предлагаемый ответ:
Кроме того, следующее не компилируется:
main = ((.) print runST) fourty_two -- (5)
Это то же самое, что и (1 ), за исключением того, что не используется инфиксная версия .
.
В результате кажется, что GHC имеет специальные правила как для $
, так и для .
, но только для их инфиксных версий.