Lower precedence for {-# UNPACK #-}

The {-# UNPACK #-} pragma is not valid inside a type but binds more tightly than function application. This is suboptimal because it contradicts user expectations (#14761) and forces unnecessary parenthesization of types. We propose to lower the precedence of {-# UNPACK #-}.

Motivation

Compare the following declarations:

data A = A { a :: {-# UNPACK #-} Maybe Int }
data B = B { b :: {-# UNPACK #-} (Maybe Int) }

While B is accepted (without warning when -XStrictData is on), A fails with the following error:

<interactive>:1:21: error:
     Unexpected strictness annotation: {-# UNPACK #-}Mayb
e
     In the type {-# UNPACK #-}Maybe Int
      In the definition of data constructor A
      In the data declaration for A

This happens because it is parsed as ({-# UNPACK #-} Maybe) Int, but {-# UNPACK #-} is only valid at the outer level of a type in a data constructor field.

In GADT declarations, a similar issue occurs:

data A where A :: {-# UNPACK #-} Maybe Int -> A
data B where B :: {-# UNPACK #-} (Maybe Int) -> B

Proposed Change Specification

Lower the precedence of {-# UNPACK #-} and {-# NOUNPACK #-} so that they bind as loosely as possible, but tighter than (->).

Effect and Interactions

The change is conservative: strictly more programs will be accepted.

Costs and Drawbacks

None.

Alternatives

A similar argument can be made for ! and ~ when they are used as strictress/laziness annotations, but Simon Peyton Jones argues that it would “look wrong”:

Both {-# UNPACK #-} and ! only make sense at the outer level of a type in a data constructor field. But in GADT-style declarations, they can appear to be “inside” a type:

data T where K :: !(Maybe Int) -> {-# UNPACK #-} !Int -> T

Somehow ! looks as if it should bind tightly. e.g. !Maybe Int -> T looks wrong. But I agree that {-# UNPACK #-} would be better with a lower precedence.

Unresolved Questions

Should we also lower the precedence of ! and ~?

Implementation Plan

I (Vladislav Zavialov) will implement this change. Most of the work is already done in Phab:D5180.