36 | | Here, and `Applicative` is an intrinsic superclass of `Monad`. |
| 55 | Here, `Applicative` is an intrinsic superclass of `Monad`. |
| 56 | |
| 57 | === Instance declarations === |
| 58 | |
| 59 | A default superclass instance in a class declaration for class C |
| 60 | has an effect on the instance declarations for C. |
| 61 | |
| 62 | Specifically: |
| 63 | * An instance declaration |
| 64 | {{{ |
| 65 | instance Q => C ty where ...defs... |
| 66 | }}} |
| 67 | for class C generates an extra instance |
| 68 | declaration |
| 69 | {{{ |
| 70 | instance Q => Si ty where .... |
| 71 | }}} |
| 72 | for each intrinsic superclass Si of C |
| 73 | |
| 74 | * The method definitions in `...defs...` are distributed to the |
| 75 | appropriate instance declaration, according to which class |
| 76 | the method belongs to. |
| 77 | |
| 78 | * Any methods that are not specified explicitly are "filled in" |
| 79 | from the default definition given in the default superclass instance. |
| 80 | (If there is no default definition, then a warning is produced, |
| 81 | and a definition that calls `error` is used instead.) |
| 82 | |
| 83 | For example, assume the class declaration for `Monad` above. Then |
| 84 | this instance declaration: |
| 85 | {{{ |
| 86 | instance Monad m where |
| 87 | (>>=) = ...blah... |
| 88 | (<*) = ...bleh... |
| 89 | }}} |
| 90 | would generate an extra instance declaration for the instrinsic superclass `Applicative`, |
| 91 | with the methods distributed appropriately: |
| 92 | {{{ |
| 93 | instance Monad m where |
| 94 | (>>=) = ...blah... |
| 95 | |
| 96 | instance Applicative m where |
| 97 | (<*) = ...bleh... -- Programmer specified |
| 98 | |
| 99 | ff <*> fs = ff >>= \ f -> fs >>= \ s -> return (f s) |
| 100 | -- From the default superclass instance |
| 101 | }}} |
| 102 | We call these extra instance declarations an '''intrinsic instance declaration'''. |
| 103 | (The term "derived instance" is already taken!) |
| 104 | |
| 105 | This process is recursive. Since `Functor` is an intrinsic superclass of `Applicative`, |
| 106 | the intrinsic instance for `Applicative` recursively |
| 107 | generates an intrinsic instance for `Functor`: |
| 108 | {{{ |
| 109 | instance Functor m where |
| 110 | fmap = (<*>) . return -- From default superclass instance |
| 111 | }}} |
| 112 | |
| 113 | == The opt-out mechanism == |
| 114 | |
| 115 | Just because you can make default instances, they are not always the instances you want. A key example is |
| 116 | {{{ |
| 117 | instance Monad m => Monad (ReaderT r m) where ... |
| 118 | }}} |
| 119 | which would give us by default the intrinsic instance |
| 120 | {{{ |
| 121 | instance Monad m => Applicative (ReaderT r m) where ... |
| 122 | }}} |
| 123 | thus preventing us adding the more general |
| 124 | {{{ |
| 125 | instance Applicative m => Applicative (ReaderT r m) where ... |
| 126 | }}} |
| 127 | To inhibit the generation of an intrinsic instance declaration, one can use a |
| 128 | `hiding` clause in the instance declaration: |
| 129 | {{{ |
| 130 | instance Sub x where |
| 131 | ... |
| 132 | hiding instance Super |
| 133 | }}} |
| 134 | which acts to prevent the generation of instances for Super and all of |
| 135 | Super's intrinsic superclasses in turn. For example: |
| 136 | write |
| 137 | {{{ |
| 138 | instance Monad m => Monad (ReaderT r m) where ... |
| 139 | return x = ... |
| 140 | ba >>= bf = ... |
| 141 | hiding instance Applicative |
| 142 | }}} |
| 143 | The `hiding` clause applies to all the intrinsic instances generated |
| 144 | from an instance declaration. For example, we might write |
| 145 | {{{ |
| 146 | instance Monad T where |
| 147 | return x = ... |
| 148 | ba >>= bf = ... |
| 149 | hiding instance Functor |
| 150 | }}} |
| 151 | Note that `Functor` is only an indirect intrinsic superclass of `Monad`, via `Applicative`. |
| 152 | So the above instance would generate an intrinsic instance for `Applicative` but not for `Functor`. |
| 153 | |
| 154 | Jón's proposal had a more subtle opt-out policy, namely that an |
| 155 | intrinsic superclass can be quietly pre-empted by an instance for the |
| 156 | superclass from a prior or the present module. Note that to declare an |
| 157 | instance of the subclass, one must produce an instance of the |
| 158 | superclass by the same module at the latest. |
| 159 | |
| 160 | This quiet exclusion |
| 161 | policy is not enough to handle the case of multiple candidate |
| 162 | intrinsic instances arising from multiple intrinsic superclasses (e.g., |
| 163 | `Traversable` and `Monad` giving competing `Functor` instances), so some |
| 164 | explicit form is required. The question for us, then, is what should |
| 165 | happen if an intrinsic superclass not explicitly hidden were to clash |
| 166 | with an explicit instance from the same or a prior module. We could |
| 167 | |
| 168 | 1. Reject this as a duplicate instance declaration, which indeed it is. |
| 169 | 2. Allow the explicit to supersede the intrinsic default, but issue a warning suggesting to either remove the explicit instance or add an explicit opt-out, or |
| 170 | 3. Allow the explicit to supersede the intrinsic default silently. |
| 171 | |
| 172 | As it stands, we propose option 1 as somehow the principled thing to |
| 173 | do. We acknowledge that it creates an issue with legacy code, |
| 174 | precisely because there are plenty of places where we have written the |
| 175 | full stack of instances, often just doing the obvious default thing: |
| 176 | these should be cleaned up, sooner or later. |
| 177 | |
| 178 | Option 3 avoids that |
| 179 | problem but risks perplexity: if I make use of some cool package which |
| 180 | introduces some {{{Foo :: * -> *}}}, I might notice that {{{Foo}}} is |
| 181 | a monad and add a {{{Monad Foo}}} instance in my own code, expecting |
| 182 | the {{{Applicative Foo}}} instance to be generated in concert; to my |
| 183 | horror, I find my code has subtle bugs because the package introduced |
| 184 | a different, non-monadic, {{{Applicative Foo}}} instance which I'm |
| 185 | accidentally using instead. Option 2 is certainly worth considering as |
| 186 | a pragmatic transitional compromise, although the 'transitional' has a |
| 187 | dangerous tendency to be permanent. |
| 188 | |
| 189 | == Multi-headed instance declarations == |
| 190 | |
| 191 | While we're about it, to allow multi-headed instance declarations for class-disjoint conjunctions, with the same semantics for constraint duplication and method distribution as for the defaults, so |
| 192 | {{{ |
| 193 | instance S => (C x, C' x) where |
| 194 | methodOfC = ... |
| 195 | methodOfC' = ... |
| 196 | }}} |
| 197 | is short for |
| 198 | {{{ |
| 199 | instance S => C x where |
| 200 | methodOfC = ... |
| 201 | instance S => C' x where |
| 202 | methodOfC' = ... |
| 203 | }}} |
| 204 | This proposal fits handily with the [wiki:KindFact kind Fact proposal], |
| 205 | which allows multiple constraints to be abbreviated by |
| 206 | ordinary type synonyms. So we might write |
| 207 | {{{ |
| 208 | type Stringy x = (Read x, Show s) |
| 209 | instance Stringy Int where |
| 210 | read = ... |
| 211 | show = ... |
| 212 | }}} |
| 213 | The common factor is that one instance declaration is expanded into |
| 214 | several with the method definitions distributed appropriately among |
| 215 | them. |
| 216 | |
| 217 | == Details == |
50 | | |
51 | | * Let subclass instance declarations spawn intrinsic superclass instances by default -- if we have |
52 | | {{{ |
53 | | class Bar t[x] => Foo x where |
54 | | instance Bar t[x] where ... |
55 | | |
56 | | instance C => Foo s where ... |
57 | | }}} |
58 | | we automatically acquire a default superclass instance |
59 | | {{{ |
60 | | instance C => Bar t[s] where ... |
61 | | }}} |
62 | | |
63 | | * Let subclass instance declarations provide and override the methods of their intrinsic superclasses with no extra delimitation; so we may write |
64 | | {{{ |
65 | | instance Monad Blah where |
66 | | return x = ... |
67 | | ba >>= bf = ... |
68 | | }}} |
69 | | and acquire the Monad instance, along with fully formed Applicative and Functor instances. By requiring that intrinsic superclasses be class-distinct, we ensure that the distribution of methods to spawned instances is unambiguous. Moreover, local overrides beat the default. If we write |
70 | | {{{ |
71 | | instance Monad Blah where |
72 | | return x = ... |
73 | | ba >>= bf = ... |
74 | | bs >> bt = ... |
75 | | }}} |
76 | | we override the default (>>) but keep the (<*>) in the spawned Applicative instance. |
77 | | |
78 | | * To inhibit default-spawning with the syntax |
79 | | {{{ |
80 | | instance Sub x where |
81 | | ... |
82 | | hiding instance Super |
83 | | }}} |
84 | | which acts to prevent the generation of instances for Super and all of Super's intrinsic superclasses in turn. We need this, so that we can write |
85 | | {{{ |
86 | | instance Monad Blah where |
87 | | return x = ... |
88 | | ba >>= bf = ... |
89 | | hiding instance Functor |
90 | | |
91 | | instance Traversable Blah where |
92 | | traverse f bx = ... -- inducing a default implementation of Functor |
93 | | }}} |
94 | | or indeed to turn off all the defaults and provide a standalone Functor instance. |
95 | | |
96 | | * While we're about it, to allow multi-headed instance declarations for class-disjoint conjunctions, with the same semantics for constraint duplication and method distribution as for the defaults, so |
97 | | {{{ |
98 | | instance S => (C x, C' x) where |
99 | | methodOfC = ... |
100 | | methodOfC' = ... |
101 | | }}} |
102 | | is short for |
103 | | {{{ |
104 | | instance S => C x where |
105 | | methodOfC = ... |
106 | | instance S => C' x where |
107 | | methodOfC' = ... |
108 | | }}} |
109 | | |
110 | | This proposal fits handily with the [wiki:KindFact kind Fact proposal], which allows multiple constraints to be abbreviated by ordinary type synonyms. |
111 | | |
112 | | Default superclass instances are implemented in the [http://personal.cis.strath.ac.uk/~conor/pub/she/superclass.html Strathclyde Haskell Enhancement]. They should enable some tidying of the library, with relatively few tears. Moreover, they should allow us to deepen type class hierarchies as we learn. Retaining backward compatibility in relative silence is the motivation for an opt-in default. |
113 | | |
114 | | == Discussion == |
115 | | |
116 | | Oleg and others note: just because you can make default instances, they are not always the instances you want. A key example is |
117 | | {{{ |
118 | | instance Monad m => Monad (ReaderT r m) where ... |
119 | | }}} |
120 | | which would give us by default |
121 | | {{{ |
122 | | instance Monad m => Applicative (ReaderT r m) where ... |
123 | | }}} |
124 | | thus preventing us adding the more general |
125 | | {{{ |
126 | | instance Applicative m => Applicative (ReaderT r m) where ... |
127 | | }}} |
128 | | The opt-out is crucial, but relatively cheap. |
129 | | |
130 | | Jón's proposal had a more subtle opt-out policy, namely that an intrinsic superclass can be quietly pre-empted by an instance for the superclass from a prior or the present module. Note that to declare an instance of the subclass, one must produce an instance of the superclass by the same module at the latest. This quiet exclusion policy is not enough to handle the case of multiple candidate instances arising from multiple intrinsic superclasses (e.g., Traversable and Monad giving competing Functor instances), so some explicit form is required. The question for us, then, is what should happen if an intrinsic superclass not explicitly hidden were to clash with an explicit instance from the same or a prior module. We could |
131 | | |
132 | | 1. reject this as a duplicate instance declaration, which indeed it is, or |
133 | | 2. allow the explicit to supersede the intrinsic default, but issue a warning suggesting to either remove the explicit instance or add an explicit opt-out, or |
134 | | 3. allow the explicit to supersede the intrinsic default silently. |
135 | | |
136 | | As it stands, we propose option 1 as somehow the principled thing to do. We acknowledge that it creates an issue with legacy code, precisely because there are plenty of places where we have written the full stack of instances, often just doing the obvious default thing: these should be cleaned up, sooner or later. Option 3 avoids that problem but risks perplexity: if I make use of some cool package which introduces some {{{Foo :: * -> *}}}, I might notice that {{{Foo}}} is a monad and add a {{{Monad Foo}}} instance in my own code, expecting the {{{Applicative Foo}}} instance to be generated in concert; to my horror, I find my code has subtle bugs because the package introduced a different, non-monadic, {{{Applicative Foo}}} instance which I'm accidentally using instead. Option 2 is certainly worth considering as a pragmatic transitional compromise, although the 'transitional' has a dangerous tendency to be permanent. |
| 231 | By requiring that intrinsic superclasses be class-distinct, we ensure that the distribution of methods to spawned instances is unambiguous. |
| 232 | |