You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: language/Roles.md
+10-5Lines changed: 10 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -16,7 +16,7 @@ foreign import data Nominal :: Type -> Type
16
16
17
17
`Coercible (Nominal a) (Nominal b)` does not hold, even when `Coercible a b` does.
18
18
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.
20
20
21
21
Nominal roles are also inferred for constrained parameters:
22
22
@@ -108,17 +108,22 @@ Here the parameter appears at _representational_ (under the `In` constructor) an
108
108
109
109
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.
110
110
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.
112
112
113
113
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.
114
114
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):
116
118
117
119
```purescript
118
120
type role Effect representational
119
-
type role Map nominal representational
120
121
```
121
122
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
+
```
123
128
124
129
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