Skip to content

Commit cdbed27

Browse files
authored
Fix broken link and improve the roles annotations section (#376)
* Fix broken link to the RoleAnnotations GHC extension * Improve the roles annotations section * fixup! Improve the roles annotations section
1 parent f2f1c18 commit cdbed27

File tree

1 file changed

+10
-5
lines changed

1 file changed

+10
-5
lines changed

language/Roles.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ foreign import data Nominal :: Type -> Type
1616

1717
`Coercible (Nominal a) (Nominal b)` does not hold, even when `Coercible a b` does.
1818

19-
Albeit a safe default, this is often too constraining. Such coercions can be allowed with a [role annotation](#role-annotations) when it is known to be safe.
19+
Albeit a safe default, this is often too constraining. More coercions can be allowed with a [role annotation](#role-annotations) when it is known to be safe.
2020

2121
Nominal roles are also inferred for constrained parameters:
2222

@@ -108,17 +108,22 @@ Here the parameter appears at _representational_ (under the `In` constructor) an
108108

109109
Inferring _nominal_ roles for foreign data types is safe but can be too constraining sometimes. For example this prevents to coerce `Effect Age` to `Effect Int`, even though they actually have the same runtime representation.
110110

111-
The roles of foreign data types can thus be loosened with explicit role annotations, similar to the [RoleAnnotations](https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#role-annotations) GHC extension.
111+
The roles of foreign data types can thus be loosened with explicit role annotations, similar to the [RoleAnnotations](https://downloads.haskell.org/ghc/latest/docs/html/users_guide/exts/roles.html#extension-RoleAnnotations) GHC extension.
112112

113113
Conversely, we might want to strengthen the roles of parameters with invariants invisible to the type system. Maps are the canonical example of this: the shape of their underlying tree rely on the `Ord` instance of their keys, but the `Ord` instance of a newtype may behave differently than the one of the wrapped type so it would be unsafe to allow coercions between `Map k1 a` and `Map k2 a`, even when `Coercible k1 k2` holds.
114114

115-
A role annotation starts with `type role`, then the name of the annotated type and the role (`nominal`, `representational` or `phantom`) of each parameters of the type:
115+
A role annotation starts with `type role`, then the name of the annotated type and the role (`nominal`, `representational` or `phantom`) of each parameters of the type. Role annotations are only allowed for data and newtype declarations. They have to immediately follow the annotated type declaration.
116+
117+
For example this role annotation relaxes the role inferred for the parameter of `Effect` (which would be _nominal_ otherwise):
116118

117119
```purescript
118120
type role Effect representational
119-
type role Map nominal representational
120121
```
121122

122-
Role annotations are only allowed for data and newtype declarations. They have to immediately follow the annotated type declaration.
123+
and this one strengthens the role inferred for the first parameter of `Map` (which would be _representational_ otherwise), leaving its second parameter _representational_:
124+
125+
```purescript
126+
type role Map nominal representational
127+
```
123128

124129
Annotated roles are compared against the roles inferred by the compiler so it is not possible to compromise safety by ascribing too permissive roles, except for foreign types.

0 commit comments

Comments
 (0)