I also note that the definition of isBanged is confusing:

    isBanged :: HsBang -> Bool
    isBanged HsNoBang                  = False
    isBanged (HsUserBang Nothing bang) = bang
    isBanged _                         = True

Why is `HsUserBang (Just False) False`, corresponding to a NOUNPACK annotations with a missing "!", considered "banged"?

On Thu, Jan 8, 2015 at 8:36 AM, Johan Tibell <johan.tibell@gmail.com> wrote:
HsBang is defined as:

    -- HsBang describes what the *programmer* wrote
    -- This info is retained in the DataCon.dcStrictMarks field
    data HsBang
      = HsUserBang   -- The user's source-code request
           (Maybe Bool)       -- Just True    {-# UNPACK #-}
                              -- Just False   {-# NOUNPACK #-}
                              -- Nothing      no pragma
           Bool               -- True <=> '!' specified

      | HsNoBang              -- Lazy field
                              -- HsUserBang Nothing False means the same as HsNoBang

      | HsUnpack              -- Definite commitment: this field is strict and unboxed
           (Maybe Coercion)   --    co :: arg-ty ~ product-ty

      | HsStrict              -- Definite commitment: this field is strict but not unboxed

This data type is a bit unclear to me:

 * What are the reasons for the following constructor overlaps?
   * `HsNoBang` and `HsUserBang Nothing False`
   * `HsStrict` and `HsUserBang Nothing True`
   * `HsUnpack mb_co` and `HsUserBang (Just True) True`

* Why is there a coercion in `HsUnpack` but not in `HsUserBang (Just True) True`?

* Is there a difference in what the user wrote in the case of HsUserBang and HsNoBang/HsUnpack/HsStrict e.g are the latter three generated by the compiler as opposed to being written by the user (the function documentation notwithstanding)?

A very related function is isBanged:

    isBanged :: HsBang -> Bool
    isBanged HsNoBang                  = False
    isBanged (HsUserBang Nothing bang) = bang
    isBanged _                         = True

What's the meaning of this function? Is it intended to communicate what the user wrote or whether result of what the user wrote results in a strict function?

Context: I'm adding a new StrictData language pragma [1] that makes fields strict by default and a '~' annotation of fields to reverse the default behavior. My intention is to change HsBang like so:

    -       Bool               -- True <=> '!' specified
    +       (Maybe Bool)       -- True <=> '!' specified, False <=> '~'
    +                          -- specified, Nothing <=> unspecified

1. https://ghc.haskell.org/trac/ghc/wiki/StrictPragma

-- Johan