
#14131: Difference between newtype and newtype instance -------------------------------------+------------------------------------- Reporter: Iceland_jack | Owner: (none) Type: bug | Status: patch Priority: normal | Milestone: Component: Compiler | Version: 8.2.1 Resolution: | Keywords: TypeFamilies Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: #7938, #9574, | Differential Rev(s): Phab:D3872 #13985 | Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj): I'm not happy with Phab:D3872. Currently we have {{{ type HsTyPats pass = HsImplicitBndrs pass [LHsType pass] }}} That sugggests that the implicit binders scope only over the patterns. But as we know, they don't. They scope over the RHS too. And indeed, as this ticket discusses, we may have variables that are implicitly bound in the RHS, but are not even mentioned on the LHS. These `HsTyPats` are used in `DataFamInstDecl` and `TyFamInstEqn` (only). For the latter: Currently we have {{{ type TyFamInstEqn pass = TyFamEqn pass (HsTyPats pass) type TyFamDefltEqn pass = TyFamEqn pass (LHsQTyVars pass) data TyFamEqn pass pats = TyFamEqn { tfe_tycon :: Located (IdP pass) , tfe_pats :: pats , tfe_fixity :: LexicalFixity -- ^ Fixity used in the declaration , tfe_rhs :: LHsType pass } }}} where the implicit binders inside `tfe_pats` weirdly scopes over the `tfe_rhs`. Instead we can have {{{ type TyFamInstEqn pass = HsImplicitBndrs (TyFamEqn pass [HsType pass]) type TyFamDefltEqn pass = HsImplicitBndrs (TyFamEqn pass [LHsTyVarBndr pass]) }}} I have not worked through the details, but it seems right to wrap the implicit binders around everything that they scopes over. I suspect that'll make the code easier too. It's similar for `DataFamInstDecl`. Currently we have: {{{ data DataFamInstDecl pass = DataFamInstDecl { dfid_tycon :: Located (IdP pass) , dfid_pats :: HsTyPats pass , dfid_fixity :: LexicalFixity , dfid_defn :: HsDataDefn pass , dfid_fvs :: PostRn pass NameSet } }}} Instead we could have {{{ type DataFamInstDecl pass -- Implicit bndrs here = HsImplicitBndrs pass (DataFamInstEqn pass) data DataFamInstEqn pass = DataFamInstEqn { dfid_tycon :: Located (IdP pass) , dfid_pats :: [LHsType pass] -- No implicit bndrs , dfid_fixity :: LexicalFixity , dfid_defn :: HsDataDefn pass , dfid_fvs :: PostRn pass NameSet } }}} Bubt that's still a bit strange, because the `dfid_fvs` should really be outside the `HsImplicitBndrs`. (And it is for `TyFamEqn`. So perhaps a better way would be to make `DataFamInstDecl` and `TyFamInstDecl` look a bit more like each other, thus {{{ type DataFamInstDecl pass = FamInstDecl pass (HsDataDefn pass) type TyFamINstDecl pass = FamInstDecl pass (LHsType pass) data FamInstDecl pass rhs = FamInstDecl { fid_eqn :: LFamInstEqn pass rhs , fid_fvs :: PostRn pass NameSet } type LFamInstEqn pass rhs = Located (FamInstEqn pass rhs) type FamInstEqn pass rhs = HsImplicitBndrs (FamEqn pass [LHsType] rhs) data FamEqn pass pats rhs = TyFamEqn { tfe_tycon :: Located (IdP pass) , tfe_pats :: pats , tfe_fixity :: LexicalFixity , tfe_rhs :: rhs } }}} We still need the typechecker test for comment:8. Finally: we need user-manual comments to explain what's accepted and what is rejected. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/14131#comment:9 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler