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: text/chapter6.md
-68Lines changed: 0 additions & 68 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -392,74 +392,6 @@ forall a. Semiring a => a -> a
392
392
393
393
Here, we might have annotated this function as `Int -> Int`, or `Number -> Number`, but PSCi shows us that the most general type works for any `Semiring`, allowing us to use our function with both `Int`s and `Number`s.
394
394
395
-
## Overlapping and Orphan Instances
396
-
397
-
PureScript has another rule regarding type class instances, called the _overlapping instances rule_. Whenever a type class instance is required at a function call site, PureScript will use the information inferred by the type checker to choose the correct instance. At that time, there should be exactly one appropriate instance for that type. If there are multiple valid instances, then it is unclear which instance to select, and the compiler will issue an error.
398
-
399
-
To demonstrate this, we can try creating two conflicting type class instances for an example type. In the following code, we create two overlapping `Show` instances for the type `T`:
400
-
401
-
```haskell
402
-
moduleOverlappedwhere
403
-
404
-
importPrelude
405
-
406
-
dataT=T
407
-
408
-
instanceshowT1::ShowTwhere
409
-
show _ ="Instance 1"
410
-
411
-
instanceshowT2::ShowTwhere
412
-
show _ ="Instance 2"
413
-
```
414
-
415
-
This module will not compile. The overlapping instances rule will be enforced, resulting in an error:
416
-
417
-
```text
418
-
Overlapping type class instances found for Data.Show.Show T
419
-
```
420
-
421
-
Furthermore, PureScript forbids _orphan instances_. An _orphan instance_ is an instance that is defined outside of both the module which defined the class and the module which defined the type. A problem with orphan instances is that they let library creators evade explicit violations of the overlapping instances rule, while potentially setting-up their users for instance collisions.
422
-
423
-
For example, consider our original type `T`:
424
-
```hs
425
-
moduleTwhere
426
-
427
-
dataT=T
428
-
```
429
-
430
-
And a library that defines an orphan `Show` instance for `T`:
431
-
```hs
432
-
moduleLibAwhere
433
-
434
-
importT
435
-
importPrelude
436
-
437
-
instanceshowT1::ShowTwhere
438
-
show _ ="Instance 1"
439
-
```
440
-
441
-
If we were to include `LibA` in our project, there would be no overlap issues. But let's say we later include `LibB`, which has the following implementation with another orphan instance:
442
-
```hs
443
-
moduleLibBwhere
444
-
445
-
importT
446
-
importPrelude
447
-
448
-
instanceshowT2::ShowTwhere
449
-
show _ ="Instance 2"
450
-
```
451
-
452
-
Now we're faced with an overlapping instance dilemma. To address this problem head-on, PureScript simply bans orphan instances, and would present the creator of `LibA` (and `LibB`) with the following error:
453
-
```text
454
-
Orphan instance showT1 found for Data.Show.Show T
455
-
456
-
This problem can be resolved by declaring the instance in Data.Show or T, or by defining the instance on a newtype wrapper.
457
-
```
458
-
459
-
By forcing instances to be defined in either the module which defined the class or the module which defined the type, PureScript guarantees that all instances are globally unique across the entire ecosystem.
460
-
461
-
If it is truly the case that there are two valid type class instances for a type, satisfying the appropriate laws, then a common approach is to define newtypes which wrap the existing type. Since different newtypes are allowed to have different type class instances under the overlapping instances rule, there is no longer an issue. This approach is taken in PureScript's standard libraries, for example in the `maybe` package, the `Maybe a` type has multiple valid instances for the `Monoid` type class via `newtype` wrappers `First` and `Last`.
462
-
463
395
## Instance Dependencies
464
396
465
397
Just as the implementation of functions can depend on type class instances using constrained types, so can the implementation of type class instances depend on other type class instances. This provides a powerful form of program inference, in which the implementation of a program can be inferred using its types.
0 commit comments