|
|
# Proposal: NoDatatypeContexts
|
|
|
|
|
|
|
|
|
<table><tr><th> Ticket </th>
|
|
|
<th>[\#139](https://gitlab.haskell.org//haskell/prime/issues/139)</th></tr>
|
|
|
<th> TODO
|
|
|
</th></tr>
|
|
|
<tr><th> Dependencies </th>
|
|
|
<th></th></tr>
|
|
|
<th>
|
|
|
</th></tr>
|
|
|
<tr><th> Related </th>
|
|
|
<th></th></tr></table>
|
|
|
<th>
|
|
|
</th></tr></table>
|
|
|
|
|
|
|
|
|
## Compiler support
|
|
|
|
|
|
|
|
|
<table><tr><th> GHC </th>
|
|
|
<th> full in HEAD (-XNoDatatypeContexts)
|
|
|
<th> full (-XNoDatatypeContexts)
|
|
|
</th></tr>
|
|
|
<tr><th> nhc98 </th>
|
|
|
<th> none
|
|
|
<th> none
|
|
|
</th></tr>
|
|
|
<tr><th> Hugs </th>
|
|
|
<th> none
|
|
|
<th> none
|
|
|
</th></tr>
|
|
|
<tr><th> UHC </th>
|
|
|
<th> none
|
|
|
<th> none
|
|
|
</th></tr>
|
|
|
<tr><th> JHC </th>
|
|
|
<th> none
|
|
|
<th> none
|
|
|
</th></tr>
|
|
|
<tr><th> LHC </th>
|
|
|
<th> none
|
|
|
<th> none
|
|
|
</th></tr></table>
|
|
|
|
|
|
|
|
|
## Summary
|
|
|
|
|
|
|
|
|
H98 and H2010 allow a context to be given for datatypes, e.g. the `Eq a` in
|
|
|
|
|
|
H98 and H2010 allow a context to be given for datatypes, e.g.
|
|
|
|
|
|
|
|
|
```wiki
|
|
|
data Eq a => Foo a = Constr a
|
... | ... | @@ -40,14 +49,18 @@ data Eq a => Foo a = Constr a |
|
|
|
|
|
This proposal is to remove support for that context.
|
|
|
|
|
|
|
|
|
## Description
|
|
|
|
|
|
|
|
|
|
|
|
Datatype contexts (called "stupid theta" in GHC sources) appear, at first glance, to be very useful, but in actual fact they are not as useful as they seem.
|
|
|
|
|
|
|
|
|
|
|
|
One might expect that, with the above `Foo` type, one could write
|
|
|
|
|
|
|
|
|
```wiki
|
|
|
isEq :: Foo a -> Foo a -> Bool
|
|
|
isEq (Constr x) (Constr y) = x == y
|
... | ... | @@ -56,6 +69,7 @@ isEq (Constr x) (Constr y) = x == y |
|
|
|
|
|
and the compiler would know that there is an `Eq a` instance from the datatype context. However, this is not the case. We instead must write
|
|
|
|
|
|
|
|
|
```wiki
|
|
|
isEq :: Eq a => Foo a -> Foo a -> Bool
|
|
|
isEq (Constr x) (Constr y) = x == y
|
... | ... | @@ -64,6 +78,7 @@ isEq (Constr x) (Constr y) = x == y |
|
|
|
|
|
In fact, we cannot even write
|
|
|
|
|
|
|
|
|
```wiki
|
|
|
getVal :: Foo a -> a
|
|
|
getVal (Constr x) = x
|
... | ... | @@ -72,6 +87,7 @@ getVal (Constr x) = x |
|
|
|
|
|
We must write
|
|
|
|
|
|
|
|
|
```wiki
|
|
|
getVal :: Eq a => Foo a -> a
|
|
|
getVal (Constr x) = x
|
... | ... | @@ -81,13 +97,14 @@ getVal (Constr x) = x |
|
|
instead.
|
|
|
|
|
|
|
|
|
|
|
|
When we would expect the compiler to have the instance already available, in actual fact we have to provide it ourselves. The problem is that the constraint is not actually on the datatype, but rather, on the type of the constructor. Worse, the dictionary is not stored in the constructor, but simply discarded.
|
|
|
|
|
|
### Effect of removing datatype contexts
|
|
|
|
|
|
|
|
|
It is possible to write programs whose behaviour changes when datatype contexts are removed, e.g. with:
|
|
|
|
|
|
|
|
|
```wiki
|
|
|
data Floating a => Foo a = Constr a
|
|
|
|
... | ... | @@ -96,8 +113,10 @@ getIncVal (Constr x) = x + 1 |
|
|
foo = show (getIncVal (Constr 1))
|
|
|
```
|
|
|
|
|
|
|
|
|
`foo` is `"2.0"`, while with
|
|
|
|
|
|
|
|
|
```wiki
|
|
|
data Foo a = Constr a
|
|
|
|
... | ... | @@ -106,16 +125,21 @@ getIncVal (Constr x) = x + 1 |
|
|
foo = show (getIncVal (Constr 1))
|
|
|
```
|
|
|
|
|
|
|
|
|
`foo` is `"2"`. Likewise it is possible that a program will fail to compile when datatype contexts are removed. However, in practice removing datatype contexts is unlikely to affect the behaviour of any real programs.
|
|
|
|
|
|
|
|
|
What removing the datatype contexts from a source file *will* do is make some previously illegal programs legal. However, we do not believe that the power that the datatype contexts feature provides is worth the burden the language construct places on implementors, documentors and educators. Other extensions being worked on, such as GADTs, have a much higher power to weight ratio.
|
|
|
|
|
|
What it will do is to make some previously illegal programs legal. However, we do not believe that the power that this provides is worth the burden the language construct places on implementors, documentors and educators. Other extensions being worked on, such as GADTs, have a much higher power to weight ratio.
|
|
|
|
|
|
|
|
|
## Current usage
|
|
|
|
|
|
|
|
|
|
|
|
There are 4 modules in base 4.3 that use datatype contexts:
|
|
|
|
|
|
|
|
|
- Control.Arrow
|
|
|
- Data.Complex
|
|
|
- GHC.Arr
|
... | ... | @@ -125,8 +149,10 @@ There are 4 modules in base 4.3 that use datatype contexts: |
|
|
In most cases, the type is specified in the H98 and H2010 report.
|
|
|
|
|
|
|
|
|
|
|
|
Doing a Hackage regression test with GHC 6.13.20100710, of the 2219 packages on Hackage, cabal-install is able to make an installation plan for 920, and GHC is actually able to compile 590. Of those 590, these 15 then fail if datatype contexts are turned off:
|
|
|
|
|
|
|
|
|
- MonadRandom
|
|
|
- PriorityChansConverger
|
|
|
- Yampa
|
... | ... | @@ -146,31 +172,22 @@ Doing a Hackage regression test with GHC 6.13.20100710, of the 2219 packages on |
|
|
|
|
|
Making these packages buildable is assumed to be as simple as removing the datatype contexts, but this has not been verified.
|
|
|
|
|
|
### Discussion
|
|
|
|
|
|
|
|
|
The proposal was discussed in
|
|
|
[ http://www.haskell.org/pipermail/haskell-prime/2010-July/003249.html](http://www.haskell.org/pipermail/haskell-prime/2010-July/003249.html)
|
|
|
|
|
|
|
|
|
In the thread, it was pointed out that DrIFT uses the context as a hint for how to derive instances. However, other GP techniques and tools, which do not need the context, can be used instead.
|
|
|
## Report Delta
|
|
|
|
|
|
|
|
|
It was also pointed out that they can be used as a hack to give the kind of an unused type variable, but there are other hacks that can be used instead (or the `KindSignatures` extension).
|
|
|
|
|
|
Changes relative to H2010 report.
|
|
|
|
|
|
It was also pointed out that we could make the contexts do something useful instead, but there is no proposal for that, and it would probably overlap with other extensions such as existential types and GADTs.
|
|
|
|
|
|
## Report Delta
|
|
|
|
|
|
In [ Section 4](http://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-620004):
|
|
|
|
|
|
Changes relative to H2010 report.
|
|
|
|
|
|
|
|
|
In [ Section 4](http://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-620004):
|
|
|
Replace:
|
|
|
|
|
|
|
|
|
Replace:
|
|
|
|
|
|
```
|
|
|
|
... | ... | @@ -182,8 +199,12 @@ topdecl -> |
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
topdecl ->
|
... | ... | @@ -193,46 +214,68 @@ topdecl -> |
|
|
...
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
In [ Section 4.2.1](http://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-690004.2.1):
|
|
|
|
|
|
|
|
|
|
|
|
Replace:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
topdecl -> data [context =>] simpletype [= constrs] [deriving]
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
topdecl -> data simpletype [= constrs] [deriving]
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Replace:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
An algebraic datatype declaration has the form: data cx => T u1 … uk = K1 t11 … t1k1 | ⋅⋅⋅ | Kn tn1 … tnkn where cx is a context.
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
An algebraic datatype declaration has the form: data T u1 … uk = K1 t11 … t1k1 | ⋅⋅⋅ | Kn tn1 … tnkn.
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Replace:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
The types of the data constructors are given by: Ki :: ∀ u1 … uk. cxi ⇒ ti1 → ⋅⋅⋅ → tiki → (T u1 … uk)
|
... | ... | @@ -242,8 +285,12 @@ any other type variable to appear in cx or on the right-hand-side. |
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
The types of the data constructors are given by: Ki :: ∀ u1 … uk. ti1 → ⋅⋅⋅ → tiki → (T u1 … uk).
|
... | ... | @@ -252,24 +299,36 @@ type variable to appear on the right-hand-side. |
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Replace:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
data Eq a => Set a = NilSet | ConsSet a (Set a)
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
data Set a = NilSet | ConsSet a (Set a)
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Replace:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
NilSet :: ∀ a. Set a
|
... | ... | @@ -282,8 +341,12 @@ the function f has inferred type Eq a => Set a -> a. The context in the data dec |
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
NilSet :: ∀ a. Set a
|
... | ... | @@ -291,8 +354,12 @@ ConsSet :: ∀ a. a → Set a → Set a |
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Replace:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
Translation: A declaration of the form data cx => T u1 … uk = … | K s1 … sn | … where each si is either of the form !ti or ti,
|
... | ... | @@ -302,8 +369,12 @@ Pattern matching on K is not affected by strictness flags. |
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
Translation: A declaration of the form data T u1 … uk = … | K s1 … sn | … where each si is either of the form !ti or ti,
|
... | ... | @@ -312,51 +383,75 @@ apply function $ if si is of the form ti, and opi is the strict apply function $ |
|
|
Pattern matching on K is not affected by strictness flags.
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
In [ Section 4.2.3](http://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-740004.2.3):
|
|
|
|
|
|
|
|
|
|
|
|
Replace:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
topdecl → newtype [context =>] simpletype = newconstr [deriving]
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
topdecl → newtype simpletype = newconstr [deriving]
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Replace:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
A declaration of the form newtype cx => T u1 … uk = N t introduces [...]
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
A declaration of the form newtype T u1 … uk = N t introduces [...]
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
In [ Section 10.5](http://www.haskell.org/onlinereport/haskell2010/haskellch10.html#x17-18000010.5):
|
|
|
|
|
|
|
|
|
|
|
|
Replace:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
topdecl ->
|
... | ... | @@ -367,8 +462,12 @@ topdecl -> |
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
with:
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
topdecl ->
|
... | ... | @@ -376,4 +475,7 @@ topdecl -> |
|
|
| data simpletype [= constrs] [deriving]
|
|
|
| newtype simpletype = newconstr [deriving]
|
|
|
...
|
|
|
``` |
|
|
\ No newline at end of file |
|
|
```
|
|
|
|
|
|
|
|
|
|