Template Haskell's TupleT considers unary tuples as a valid types.
I don't know how tuples are internally implemented in GHC, but the Haskell report (3.8) specifically establishes two as their lower size bound.
When provided a zero (or null list) arguments, all TupleT, TupP and TupE behave like the unit type (which is certainly reasonable). However, they handle argument 1 (or the singleton list) in different ways:
-
TupleP [pat]is equivalent topat(which again, is perfectly reasonable) -
TupE [exp]behaves as exp (again, it seems right)
However:
-
TupleT 1AppTVarT ''Intis a different type thanVarT ''Int
See the following two examples:
-
tupE [exp]behaves as expected:
Prelude Language.Haskell.TH> $(sigE (tupE [[|1|]]) (conT ''Int))
1
-
tupleT 1doesn't:
Prelude Language.Haskell.TH> $(sigE [|1|] (tupleT 1 `appT` conT ''Int))
<interactive>:1:2:
No instance for (Num (Int))
arising from the literal `1' at <interactive>:1:2-40
Possible fix: add an instance declaration for (Num (Int))
In the expression: $(sigE [| 1 |] (tupleT 1 `appT` conT 'Int))
In the definition of `it':
it = $(sigE [| 1 |] (tupleT 1 `appT` conT 'Int))
Probably, since unary tuples are not legal, the typechecker should simply raise an error when TupleT is found to have received 1 as argument.
Trac metadata
| Trac field | Value |
|---|---|
| Version | 6.8.2 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Template Haskell |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | Unknown |
| Architecture | Unknown |