---------------------------------------------
Make type synonyms uniform with data types
so far as infix operators are concerned
---------------------------------------------
Merge to STABLE
This allows
type (a :+: b) c d = ...
which was prevented before by accident.
I've also documented the fact that classes can be infix;
and arranged that class constraints in types can be in infix form.
f :: (a :=: b) => ....
import HsSyn
import RdrHsSyn
import HsSyn
import RdrHsSyn
-import HscTypes ( ModIface, IsBootInterface, DeprecTxt )
+import HscTypes ( IsBootInterface, DeprecTxt )
import Lexer
import RdrName
import TysWiredIn ( unitTyCon, unitDataCon, tupleTyCon, tupleCon, nilDataCon,
import Lexer
import RdrName
import TysWiredIn ( unitTyCon, unitDataCon, tupleTyCon, tupleCon, nilDataCon,
import BasicTypes ( Boxity(..), Fixity(..), FixityDirection(..), IPName(..),
Activation(..) )
import OrdList
import BasicTypes ( Boxity(..), Fixity(..), FixityDirection(..), IPName(..),
Activation(..) )
import OrdList
import Panic
import FastString
import Panic
import FastString
| decl { unLoc $1 }
tycl_decl :: { LTyClDecl RdrName }
| decl { unLoc $1 }
tycl_decl :: { LTyClDecl RdrName }
- : 'type' syn_hdr '=' ctype
- -- Note ctype, not sigtype.
+ : 'type' type '=' ctype
+ -- Note type on the left of the '='; this allows
+ -- infix type constructors to be declared
+ --
+ -- Note ctype, not sigtype, on the right
-- We allow an explicit for-all but we don't insert one
-- in type Foo a = (b,b)
-- Instead we just say b is out of scope
-- We allow an explicit for-all but we don't insert one
-- in type Foo a = (b,b)
-- Instead we just say b is out of scope
- { LL $ let (tc,tvs) = $2 in TySynonym tc tvs $4 }
+ {% do { (tc,tvs) <- checkSynHdr $2
+ ; return (LL (TySynonym tc tvs $4)) } }
| 'data' tycl_hdr constrs deriving
| 'data' tycl_hdr constrs deriving
- { L (comb4 $1 $2 $3 $4)
+ { L (comb4 $1 $2 $3 $4) -- We need the location on tycl_hdr
+ -- in case constrs and deriving are both empty
(mkTyData DataType $2 Nothing (reverse (unLoc $3)) (unLoc $4)) }
| 'data' tycl_hdr opt_kind_sig 'where' gadt_constrlist -- No deriving for GADTs
(mkTyData DataType $2 Nothing (reverse (unLoc $3)) (unLoc $4)) }
| 'data' tycl_hdr opt_kind_sig 'where' gadt_constrlist -- No deriving for GADTs
: { Nothing }
| '::' kind { Just $2 }
: { Nothing }
| '::' kind { Just $2 }
-syn_hdr :: { (Located RdrName, [LHsTyVarBndr RdrName]) }
- -- We don't retain the syntax of an infix
- -- type synonym declaration. Oh well.
- : tycon tv_bndrs { ($1, $2) }
- | tv_bndr tyconop tv_bndr { ($2, [$1,$3]) }
-
-- tycl_hdr parses the header of a type or class decl,
-- which takes the form
-- T a b
-- tycl_hdr parses the header of a type or class decl,
-- which takes the form
-- T a b
-- (Eq a, Ord b) => T a b
-- Rather a lot of inlining here, else we get reduce/reduce errors
tycl_hdr :: { Located (LHsContext RdrName, Located RdrName, [LHsTyVarBndr RdrName]) }
-- (Eq a, Ord b) => T a b
-- Rather a lot of inlining here, else we get reduce/reduce errors
tycl_hdr :: { Located (LHsContext RdrName, Located RdrName, [LHsTyVarBndr RdrName]) }
- : context '=>' type {% checkTyClHdr $1 $3 >>= return.LL }
+ : context '=>' type {% checkTyClHdr $1 $3 >>= return.LL }
| type {% checkTyClHdr (noLoc []) $1 >>= return.L1 }
-----------------------------------------------------------------------------
| type {% checkTyClHdr (noLoc []) $1 >>= return.L1 }
-----------------------------------------------------------------------------
, checkPrecP -- Int -> P Int
, checkContext -- HsType -> P HsContext
, checkPred -- HsType -> P HsPred
, checkPrecP -- Int -> P Int
, checkContext -- HsType -> P HsContext
, checkPred -- HsType -> P HsPred
- , checkTyClHdr -- HsType -> (name,[tyvar])
+ , checkTyClHdr
+ , checkSynHdr
, checkInstType -- HsType -> P HsType
, checkPattern -- HsExp -> P HsPat
, checkPatterns -- SrcLoc -> [HsExp] -> P [HsPat]
, checkInstType -- HsType -> P HsType
, checkPattern -- HsExp -> P HsPat
, checkPatterns -- SrcLoc -> [HsExp] -> P [HsPat]
#include "HsVersions.h"
import HsSyn -- Lots of it
#include "HsVersions.h"
import HsSyn -- Lots of it
-import IfaceType
-import Packages ( PackageIdH(..) )
-import HscTypes ( ModIface(..), emptyModIface, mkIfaceVerCache,
- Dependencies(..), IsBootInterface, noDependencies )
-import IfaceSyn ( IfaceDecl(..), IfaceIdInfo(..), IfaceConDecl(..), IfaceConDecls(..) )
import RdrName ( RdrName, isRdrTyVar, mkUnqual, rdrNameOcc,
isRdrTyVar, isRdrDataCon, isUnqual, getRdrName, isQual,
import RdrName ( RdrName, isRdrTyVar, mkUnqual, rdrNameOcc,
isRdrTyVar, isRdrDataCon, isUnqual, getRdrName, isQual,
- setRdrNameSpace, rdrNameModule )
-import BasicTypes ( RecFlag(..), mapIPName, maxPrecedence, initialVersion )
+ setRdrNameSpace )
+import BasicTypes ( RecFlag(..), maxPrecedence )
import Lexer ( P, failSpanMsgP )
import Lexer ( P, failSpanMsgP )
-import Kind ( liftedTypeKind )
-import HscTypes ( GenAvailInfo(..) )
import TysWiredIn ( unitTyCon )
import ForeignCall ( CCallConv, Safety, CCallTarget(..), CExportSpec(..),
DNCallSpec(..), DNKind(..), CLabelString )
import TysWiredIn ( unitTyCon )
import ForeignCall ( CCallConv, Safety, CCallTarget(..), CExportSpec(..),
DNCallSpec(..), DNKind(..), CLabelString )
-import OccName ( OccName, srcDataName, varName, isDataOcc, isTcOcc,
- occNameUserString, isValOcc )
-import BasicTypes ( initialVersion, StrictnessMark(..) )
-import Module ( Module )
+import OccName ( srcDataName, varName, isDataOcc, isTcOcc,
+ occNameUserString )
import SrcLoc
import OrdList ( OrdList, fromOL )
import Bag ( Bag, emptyBag, snocBag, consBag, foldrBag )
import SrcLoc
import OrdList ( OrdList, fromOL )
import Bag ( Bag, emptyBag, snocBag, consBag, foldrBag )
chk (L l other)
= parseError l "Type found where type variable expected"
chk (L l other)
= parseError l "Type found where type variable expected"
+checkSynHdr :: LHsType RdrName -> P (Located RdrName, [LHsTyVarBndr RdrName])
+checkSynHdr ty = do { (_, tc, tvs) <- checkTyClHdr (noLoc []) ty
+ ; return (tc, tvs) }
+
checkTyClHdr :: LHsContext RdrName -> LHsType RdrName
-> P (LHsContext RdrName, Located RdrName, [LHsTyVarBndr RdrName])
-- The header of a type or class decl should look like
checkTyClHdr :: LHsContext RdrName -> LHsType RdrName
-> P (LHsContext RdrName, Located RdrName, [LHsTyVarBndr RdrName])
-- The header of a type or class decl should look like
where
checkl (L l ty) args = check l ty args
where
checkl (L l ty) args = check l ty args
- check loc (HsTyVar t) args | not (isRdrTyVar t)
- = return (L spn (HsClassP t args))
- check loc (HsAppTy l r) args = checkl l (r:args)
- check loc (HsParTy t) args = checkl t args
- check loc _ _ = parseError loc "malformed class assertion"
+ check _loc (HsTyVar t) args | not (isRdrTyVar t)
+ = return (L spn (HsClassP t args))
+ check _loc (HsAppTy l r) args = checkl l (r:args)
+ check _loc (HsOpTy l (L loc tc) r) args = check loc (HsTyVar tc) (l:r:args)
+ check _loc (HsParTy t) args = checkl t args
+ check loc _ _ = parseError loc "malformed class assertion"
checkDictTy :: LHsType RdrName -> P (LHsType RdrName)
checkDictTy (L spn ty) = check ty []
checkDictTy :: LHsType RdrName -> P (LHsType RdrName)
checkDictTy (L spn ty) = check ty []
</sect3>
<sect3 id="infix-tycons">
</sect3>
<sect3 id="infix-tycons">
-<title>Infix type constructors</title>
+<title>Infix type constructors and classes</title>
-GHC allows type constructors to be operators, and to be written infix, very much
+GHC allows type constructors and classes to be operators, and to be written infix, very much
like expressions. More specifically:
<itemizedlist>
<listitem><para>
like expressions. More specifically:
<itemizedlist>
<listitem><para>
- A type constructor can be an operator, beginning with a colon; e.g. <literal>:*:</literal>.
+ A type constructor or class can be an operator, beginning with a colon; e.g. <literal>:*:</literal>.
The lexical syntax is the same as that for data constructors.
</para></listitem>
<listitem><para>
The lexical syntax is the same as that for data constructors.
</para></listitem>
<listitem><para>
- Types can be written infix. For example <literal>Int :*: Bool</literal>.
+ Data type and type-synonym declarations can be written infix, parenthesised
+ if you want further arguments. E.g.
+<screen>
+ data a :*: b = Foo a b
+ type a :+: b = Either a b
+ class a :=: b where ...
+
+ data (a :**: b) x = Baz a b x
+ type (a :++: b) y = Either (a,b) y
+</screen>
+ </para></listitem>
+<listitem><para>
+ Types, and class constraints, can be written infix. For example
+ <screen>
+ x :: Int :*: Bool
+ f :: (a :=: b) => a -> b
+ </screen>
</para></listitem>
<listitem><para>
Back-quotes work
</para></listitem>
<listitem><para>
Back-quotes work
<literal>Int `a` Bool</literal>. Similarly, parentheses work the same; e.g. <literal>(:*:) Int Bool</literal>.
</para></listitem>
<listitem><para>
<literal>Int `a` Bool</literal>. Similarly, parentheses work the same; e.g. <literal>(:*:) Int Bool</literal>.
</para></listitem>
<listitem><para>
- Fixities may be declared for type constructors just as for data constructors. However,
+ Fixities may be declared for type constructors, or classes, just as for data constructors. However,
one cannot distinguish between the two in a fixity declaration; a fixity declaration
sets the fixity for a data constructor and the corresponding type constructor. For example:
<screen>
one cannot distinguish between the two in a fixity declaration; a fixity declaration
sets the fixity for a data constructor and the corresponding type constructor. For example:
<screen>
Function arrow is <literal>infixr</literal> with fixity 0. (This might change; I'm not sure what it should be.)
</para></listitem>
<listitem><para>
Function arrow is <literal>infixr</literal> with fixity 0. (This might change; I'm not sure what it should be.)
</para></listitem>
<listitem><para>
- Data type and type-synonym declarations can be written infix. E.g.
-<screen>
- data a :*: b = Foo a b
- type a :+: b = Either a b
-</screen>
- </para></listitem>
-<listitem><para>
The only thing that differs between operators in types and operators in expressions is that
ordinary non-constructor operators, such as <literal>+</literal> and <literal>*</literal>
are not allowed in types. Reason: the uniform thing to do would be to make them type
The only thing that differs between operators in types and operators in expressions is that
ordinary non-constructor operators, such as <literal>+</literal> and <literal>*</literal>
are not allowed in types. Reason: the uniform thing to do would be to make them type