Skip to content

Commit 77c810f

Browse files
authored
Ch6 - Remove section on Overlapping and Orphan Instances (#242)
1 parent 9c3292a commit 77c810f

File tree

1 file changed

+0
-68
lines changed

1 file changed

+0
-68
lines changed

text/chapter6.md

Lines changed: 0 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -392,74 +392,6 @@ forall a. Semiring a => a -> a
392392

393393
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.
394394

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-
module Overlapped where
403-
404-
import Prelude
405-
406-
data T = T
407-
408-
instance showT1 :: Show T where
409-
show _ = "Instance 1"
410-
411-
instance showT2 :: Show T where
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-
module T where
426-
427-
data T = T
428-
```
429-
430-
And a library that defines an orphan `Show` instance for `T`:
431-
```hs
432-
module LibA where
433-
434-
import T
435-
import Prelude
436-
437-
instance showT1 :: Show T where
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-
module LibB where
444-
445-
import T
446-
import Prelude
447-
448-
instance showT2 :: Show T where
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-
463395
## Instance Dependencies
464396

465397
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

Comments
 (0)