Ответ
@ dfeuer охватывает обходной путь, но я думаю, что issue # 17670 объясняет , почему это происходит. Поскольку coerce
является примопом, он должен быть полностью насыщен, поэтому любое использование неявно расширяется с помощью eta. Когда вы пишете:
q = coerce
, вы действительно пишете:
q = \x -> coerce x
Первоначальное сообщение об ошибке, которое вы получаете, на самом деле является результатом ограничения мономорфизма. Если вы напишете либо:
q x = coerce x
, либо добавите расширение NoMonomorphismRestriction
, программа будет принята. К сожалению, полученный q
не является полиморфом легкомыслия c. Он создается с поднятыми типами.
Если попытаться вызвать проблему, добавив соответствующий полиморф c сигнатуру типа:
q :: forall (k :: RuntimeRep) (a :: TYPE k) (b :: TYPE k). Coercible a b => a -> b
q = coerce
, то последующие версии GH C (например, "8.11", созданный из исходного кода в прошлом месяце) дает подробное сообщение об ошибке:
BadCoerce.hs:11:5: error:
Cannot use function with levity-polymorphic arguments:
coerce :: a -> b
(Note that levity-polymorphic primops such as 'coerce' and unboxed tuples
are eta-expanded internally because they must occur fully saturated.
Use -fprint-typechecker-elaboration to display the full expression.)
Levity-polymorphic arguments: a :: TYPE k
В конечном итоге вы сталкиваетесь с запретом, что никакая переменная (в данном случае неявная переменная, введенная в eta-expand coerce
) разрешено быть levity polymorphi c. Причина, по которой q = q
работает, заключается в том, что нет расширения eta и, следовательно, нет переменной. Попробуйте q x = q x
, и он завершится ошибкой с сообщением об ошибке «тип levity-polymorphi c здесь не разрешен».