Commit bace26aa authored by Alec Theriault's avatar Alec Theriault Committed by Ryan Scott

Allow (unparenthesized) kind signatures

Summary: This allows for things like `[t :: MyKind]`, `(a :: k, b)`, and so on.

Test Plan: make TEST=T11622 && make TEST=T8708

Reviewers: RyanGlScott, bgamari, simonpj, goldfire, alanz

Reviewed By: RyanGlScott, simonpj

Subscribers: alanz, simonpj, rwbarton, mpickering, carter

GHC Trac Issues: #11622, #8708

Differential Revision: https://phabricator.haskell.org/D5173
parent 85376570
......@@ -257,7 +257,7 @@ cvtDec (ClassD ctxt cl tvs fds decs)
cvt_at_def :: LTyFamInstDecl GhcPs -> CvtM (LTyFamDefltEqn GhcPs)
-- Very similar to what happens in RdrHsSyn.mkClassDecl
cvt_at_def decl = case RdrHsSyn.mkATDefault decl of
Right def -> return def
Right (def, _) -> return def
Left (_, msg) -> failWith msg
cvtDec (InstanceD o ctxt ty decs)
......
......@@ -1245,7 +1245,7 @@ hsExprNeedsParens p = go
| otherwise = p > topPrec
go (ExplicitList{}) = False
go (RecordUpd{}) = False
go (ExprWithTySig{}) = p > topPrec
go (ExprWithTySig{}) = p >= sigPrec
go (ArithSeq{}) = False
go (EWildPat{}) = False
go (ELazyPat{}) = False
......
......@@ -735,7 +735,7 @@ patNeedsParens p = go
go (SplicePat {}) = False
go (ConPatIn _ ds) = conPatNeedsParens p ds
go cp@(ConPatOut {}) = conPatNeedsParens p (pat_args cp)
go (SigPat {}) = p > topPrec
go (SigPat {}) = p >= sigPrec
go (ViewPat {}) = True
go (CoPat _ _ p _) = go p
go (WildPat {}) = False
......
......@@ -1410,7 +1410,7 @@ ppr_mono_ty (HsTupleTy _ con tys) = tupleParens std_con (pprWithCommas ppr tys)
ppr_mono_ty (HsSumTy _ tys)
= tupleParens UnboxedTuple (pprWithBars ppr tys)
ppr_mono_ty (HsKindSig _ ty kind)
= parens (ppr_mono_lty ty <+> dcolon <+> ppr kind)
= ppr_mono_lty ty <+> dcolon <+> ppr kind
ppr_mono_ty (HsListTy _ ty) = brackets (ppr_mono_lty ty)
ppr_mono_ty (HsIParamTy _ n ty) = (ppr n <+> dcolon <+> ppr_mono_lty ty)
ppr_mono_ty (HsSpliceTy _ s) = pprSplice s
......@@ -1473,7 +1473,7 @@ hsTypeNeedsParens p = go
go (HsFunTy{}) = p >= funPrec
go (HsTupleTy{}) = False
go (HsSumTy{}) = False
go (HsKindSig{}) = False
go (HsKindSig{}) = p >= sigPrec
go (HsListTy{}) = False
go (HsIParamTy{}) = p > topPrec
go (HsSpliceTy{}) = False
......
......@@ -674,7 +674,7 @@ typeToLHsType ty
| any isInvisibleTyConBinder (tyConBinders tc)
-- We must produce an explicit kind signature here to make certain
-- programs kind-check. See Note [Kind signatures in typeToLHsType].
= noLoc $ HsKindSig NoExt lhs_ty (go (typeKind ty))
= nlHsParTy $ noLoc $ HsKindSig NoExt lhs_ty (go (typeKind ty))
| otherwise = lhs_ty
where
lhs_ty = nlHsTyConApp (getRdrName tc) (map go args')
......
......@@ -612,7 +612,7 @@ TH_QQUASIQUOTE { L _ (ITqQuasiQuote _) }
%name parseTypeSignature sigdecl
%name parseStmt maybe_stmt
%name parseIdentifier identifier
%name parseType ctype
%name parseType ktype
%name parseBackpack backpack
%partial parseHeader header
%%
......@@ -1223,7 +1223,7 @@ ty_fam_inst_eqns :: { Located [LTyFamInstEqn GhcPs] }
| {- empty -} { noLoc [] }
ty_fam_inst_eqn :: { Located ([AddAnn],TyFamInstEqn GhcPs) }
: type '=' ctype
: type '=' ktype
-- Note the use of type for the head; this allows
-- infix type constructors and type patterns
{% do { (eqn,ann) <- mkTyFamInstEqn $1 $3
......@@ -1776,6 +1776,12 @@ unpackedness :: { Located ([AddAnn], SourceText, SrcUnpackedness) }
: '{-# UNPACK' '#-}' { sLL $1 $> ([mo $1, mc $2], getUNPACK_PRAGs $1, SrcUnpack) }
| '{-# NOUNPACK' '#-}' { sLL $1 $> ([mo $1, mc $2], getNOUNPACK_PRAGs $1, SrcNoUnpack) }
-- A ktype is a ctype, possibly with a kind annotation
ktype :: { LHsType GhcPs }
: ctype { $1 }
| ctype '::' kind {% ams (sLL $1 $> $ HsKindSig noExt $1 $3)
[mu AnnDcolon $2] }
-- A ctype is a for-all type
ctype :: { LHsType GhcPs }
: 'forall' tv_bndrs '.' ctype {% hintExplicitForall (getLoc $1) >>
......@@ -1933,7 +1939,7 @@ atype :: { LHsType GhcPs }
| '(' ')' {% ams (sLL $1 $> $ HsTupleTy noExt
HsBoxedOrConstraintTuple [])
[mop $1,mcp $2] }
| '(' ctype ',' comma_types1 ')' {% addAnnotation (gl $2) AnnComma
| '(' ktype ',' comma_types1 ')' {% addAnnotation (gl $2) AnnComma
(gl $3) >>
ams (sLL $1 $> $ HsTupleTy noExt
......@@ -1945,10 +1951,8 @@ atype :: { LHsType GhcPs }
[mo $1,mc $3] }
| '(#' bar_types2 '#)' {% ams (sLL $1 $> $ HsSumTy noExt $2)
[mo $1,mc $3] }
| '[' ctype ']' {% ams (sLL $1 $> $ HsListTy noExt $2) [mos $1,mcs $3] }
| '(' ctype ')' {% ams (sLL $1 $> $ HsParTy noExt $2) [mop $1,mcp $3] }
| '(' ctype '::' kind ')' {% ams (sLL $1 $> $ HsKindSig noExt $2 $4)
[mop $1,mu AnnDcolon $3,mcp $5] }
| '[' ktype ']' {% ams (sLL $1 $> $ HsListTy noExt $2) [mos $1,mcs $3] }
| '(' ktype ')' {% ams (sLL $1 $> $ HsParTy noExt $2) [mop $1,mcp $3] }
| quasiquote { sL1 $1 (HsSpliceTy noExt (unLoc $1) ) }
| '$(' exp ')' {% ams (sLL $1 $> $ mkHsSpliceTy HasParens $2)
[mj AnnOpenPE $1,mj AnnCloseP $3] }
......@@ -1957,7 +1961,7 @@ atype :: { LHsType GhcPs }
[mj AnnThIdSplice $1] }
-- see Note [Promotion] for the followings
| SIMPLEQUOTE qcon_nowiredlist {% ams (sLL $1 $> $ HsTyVar noExt Promoted $2) [mj AnnSimpleQuote $1,mj AnnName $2] }
| SIMPLEQUOTE '(' ctype ',' comma_types1 ')'
| SIMPLEQUOTE '(' ktype ',' comma_types1 ')'
{% addAnnotation (gl $3) AnnComma (gl $4) >>
ams (sLL $1 $> $ HsExplicitTupleTy noExt ($3 : $5))
[mj AnnSimpleQuote $1,mop $2,mcp $6] }
......@@ -1970,7 +1974,7 @@ atype :: { LHsType GhcPs }
-- if you had written '[ty, ty, ty]
-- (One means a list type, zero means the list type constructor,
-- so you have to quote those.)
| '[' ctype ',' comma_types1 ']' {% addAnnotation (gl $2) AnnComma
| '[' ktype ',' comma_types1 ']' {% addAnnotation (gl $2) AnnComma
(gl $3) >>
ams (sLL $1 $> $ HsExplicitListTy noExt NotPromoted ($2 : $4))
[mos $1,mcs $5] }
......@@ -1997,14 +2001,14 @@ comma_types0 :: { [LHsType GhcPs] } -- Zero or more: ty,ty,ty
| {- empty -} { [] }
comma_types1 :: { [LHsType GhcPs] } -- One or more: ty,ty,ty
: ctype { [$1] }
| ctype ',' comma_types1 {% addAnnotation (gl $1) AnnComma (gl $2)
: ktype { [$1] }
| ktype ',' comma_types1 {% addAnnotation (gl $1) AnnComma (gl $2)
>> return ($1 : $3) }
bar_types2 :: { [LHsType GhcPs] } -- Two or more: ty|ty|ty
: ctype '|' ctype {% addAnnotation (gl $1) AnnVbar (gl $2)
: ktype '|' ktype {% addAnnotation (gl $1) AnnVbar (gl $2)
>> return [$1,$3] }
| ctype '|' bar_types2 {% addAnnotation (gl $1) AnnVbar (gl $2)
| ktype '|' bar_types2 {% addAnnotation (gl $1) AnnVbar (gl $2)
>> return ($1 : $3) }
tv_bndrs :: { [LHsTyVarBndr GhcPs] }
......@@ -2653,7 +2657,7 @@ aexp2 :: { LHsExpr GhcPs }
else [mu AnnOpenEQ $1,mu AnnCloseQ $3]) }
| '[||' exp '||]' {% ams (sLL $1 $> $ HsBracket noExt (TExpBr noExt $2))
(if (hasE $1) then [mj AnnOpenE $1,mc $3] else [mo $1,mc $3]) }
| '[t|' ctype '|]' {% ams (sLL $1 $> $ HsBracket noExt (TypBr noExt $2)) [mo $1,mu AnnCloseQ $3] }
| '[t|' ktype '|]' {% ams (sLL $1 $> $ HsBracket noExt (TypBr noExt $2)) [mo $1,mu AnnCloseQ $3] }
| '[p|' infixexp '|]' {% checkPattern empty $2 >>= \p ->
ams (sLL $1 $> $ HsBracket noExt (PatBr noExt p))
[mo $1,mu AnnCloseQ $3] }
......
......@@ -151,7 +151,8 @@ mkClassDecl loc (L _ (mcxt, tycl_hdr)) fds where_cls
; (cls, tparams, fixity, ann) <- checkTyClHdr True tycl_hdr
; mapM_ (\a -> a loc) ann -- Add any API Annotations to the top SrcSpan
; tyvars <- checkTyVarsP (text "class") whereDots cls tparams
; at_defs <- mapM (eitherToP . mkATDefault) at_insts
; (at_defs, anns) <- fmap unzip $ mapM (eitherToP . mkATDefault) at_insts
; sequence_ anns
; return (L loc (ClassDecl { tcdCExt = noExt, tcdCtxt = cxt
, tcdLName = cls, tcdTyVars = tyvars
, tcdFixity = fixity
......@@ -162,22 +163,26 @@ mkClassDecl loc (L _ (mcxt, tycl_hdr)) fds where_cls
, tcdDocs = docs })) }
mkATDefault :: LTyFamInstDecl GhcPs
-> Either (SrcSpan, SDoc) (LTyFamDefltEqn GhcPs)
-- Take a type-family instance declaration and turn it into
-- a type-family default equation for a class declaration
-> Either (SrcSpan, SDoc) (LTyFamDefltEqn GhcPs, P ())
-- ^ Take a type-family instance declaration and turn it into
-- a type-family default equation for a class declaration.
-- We parse things as the former and use this function to convert to the latter
--
-- We use the Either monad because this also called
-- from Convert.hs
-- We use the Either monad because this also called from "Convert".
--
-- The @P ()@ we return corresponds represents an action which will add
-- some necessary paren annotations to the parsing context. Naturally, this
-- is not something that the "Convert" use cares about.
mkATDefault (L loc (TyFamInstDecl { tfid_eqn = HsIB { hsib_body = e }}))
| FamEqn { feqn_tycon = tc, feqn_pats = pats, feqn_fixity = fixity
, feqn_rhs = rhs } <- e
= do { tvs <- checkTyVars (text "default") equalsDots tc pats
; return (L loc (FamEqn { feqn_ext = noExt
= do { (tvs, anns) <- checkTyVars (text "default") equalsDots tc pats
; let f = L loc (FamEqn { feqn_ext = noExt
, feqn_tycon = tc
, feqn_pats = tvs
, feqn_fixity = fixity
, feqn_rhs = rhs })) }
, feqn_rhs = rhs })
; pure (f, anns) }
mkATDefault (L _ (TyFamInstDecl (HsIB _ (XFamEqn _)))) = panic "mkATDefault"
mkATDefault (L _ (TyFamInstDecl (XHsImplicitBndrs _))) = panic "mkATDefault"
......@@ -774,7 +779,10 @@ checkTyVarsP :: SDoc -> SDoc -> Located RdrName -> [LHsType GhcPs]
-> P (LHsQTyVars GhcPs)
-- Same as checkTyVars, but in the P monad
checkTyVarsP pp_what equals_or_where tc tparms
= eitherToP $ checkTyVars pp_what equals_or_where tc tparms
= do { let checkedTvs = checkTyVars pp_what equals_or_where tc tparms
; (tvs, anns) <- eitherToP checkedTvs
; anns
; pure tvs }
eitherToP :: Either (SrcSpan, SDoc) a -> P a
-- Adapts the Either monad to the P monad
......@@ -782,16 +790,24 @@ eitherToP (Left (loc, doc)) = parseErrorSDoc loc doc
eitherToP (Right thing) = return thing
checkTyVars :: SDoc -> SDoc -> Located RdrName -> [LHsType GhcPs]
-> Either (SrcSpan, SDoc) (LHsQTyVars GhcPs)
-- Check whether the given list of type parameters are all type variables
-- (possibly with a kind signature)
-- We use the Either monad because it's also called (via mkATDefault) from
-- Convert.hs
-> Either (SrcSpan, SDoc)
( LHsQTyVars GhcPs -- the synthesized type variables
, P () ) -- action which adds annotations
-- ^ Check whether the given list of type parameters are all type variables
-- (possibly with a kind signature).
-- We use the Either monad because it's also called (via 'mkATDefault') from
-- "Convert".
checkTyVars pp_what equals_or_where tc tparms
= do { tvs <- mapM chk tparms
; return (mkHsQTvs tvs) }
= do { (tvs, anns) <- fmap unzip $ mapM (chkParens []) tparms
; return (mkHsQTvs tvs, sequence_ anns) }
where
chk (L _ (HsParTy _ ty)) = chk ty
-- Keep around an action for adjusting the annotations of extra parens
chkParens :: [AddAnn] -> LHsType GhcPs
-> Either (SrcSpan, SDoc) (LHsTyVarBndr GhcPs, P ())
chkParens acc (L l (HsParTy _ ty)) = chkParens (mkParensApiAnn l ++ acc) ty
chkParens acc ty = case chk ty of
Left err -> Left err
Right tv@(L l _) -> Right (tv, addAnnsAt l (reverse acc))
-- Check that the name space is correct!
chk (L l (HsKindSig _ (L lv (HsTyVar _ _ (L _ tv))) k))
......
......@@ -50,6 +50,10 @@ Language
data D1 = forall a b. (a + b) => D1 a b
data D2 = forall a b. a + b => D2 a b -- now allowed
- The requirement that kind signatures always be parenthesized has been relaxed.
For instance, it is now permissible to write ``Proxy '(a :: A, b :: B)``
(previous GHC versions required extra parens: ``Proxy '((a :: A), (b :: B))``).
Compiler
~~~~~~~~
......
......@@ -22,8 +22,10 @@
((Test11018.hs:(12,1)-(15,7),AnnEqual), [Test11018.hs:13:5]),
((Test11018.hs:(12,1)-(15,7),AnnSemi), [Test11018.hs:17:1]),
((Test11018.hs:12:21-32,AnnCloseP), [Test11018.hs:12:32]),
((Test11018.hs:12:21-32,AnnDcolonU), [Test11018.hs:12:24]),
((Test11018.hs:12:21-32,AnnOpenP), [Test11018.hs:12:21]),
((Test11018.hs:12:22-31,AnnCloseP), [Test11018.hs:12:32]),
((Test11018.hs:12:22-31,AnnDcolonU), [Test11018.hs:12:24]),
((Test11018.hs:12:22-31,AnnOpenP), [Test11018.hs:12:21]),
((Test11018.hs:12:26,AnnRarrow), [Test11018.hs:12:28-29]),
((Test11018.hs:12:26-31,AnnRarrow), [Test11018.hs:12:28-29]),
((Test11018.hs:(13,16)-(15,7),AnnCloseC), [Test11018.hs:15:7]),
......@@ -120,8 +122,10 @@
((Test11018.hs:(37,1)-(40,7),AnnEqual), [Test11018.hs:38:5]),
((Test11018.hs:(37,1)-(40,7),AnnSemi), [Test11018.hs:42:1]),
((Test11018.hs:37:22-32,AnnCloseP), [Test11018.hs:37:32]),
((Test11018.hs:37:22-32,AnnDcolonU), [Test11018.hs:37:25]),
((Test11018.hs:37:22-32,AnnOpenP), [Test11018.hs:37:22]),
((Test11018.hs:37:23-31,AnnCloseP), [Test11018.hs:37:32]),
((Test11018.hs:37:23-31,AnnDcolonU), [Test11018.hs:37:25]),
((Test11018.hs:37:23-31,AnnOpenP), [Test11018.hs:37:22]),
((Test11018.hs:37:27,AnnRarrowU), [Test11018.hs:37:29]),
((Test11018.hs:37:27-31,AnnRarrowU), [Test11018.hs:37:29]),
((Test11018.hs:(38,17)-(40,7),AnnCloseC), [Test11018.hs:40:7]),
......
......@@ -11,8 +11,8 @@
((Test11321.hs:(12,1)-(17,27),AnnInstance), [Test11321.hs:12:6-13]),
((Test11321.hs:(12,1)-(17,27),AnnSemi), [Test11321.hs:18:1]),
((Test11321.hs:12:20-29,AnnCloseP), [Test11321.hs:12:29]),
((Test11321.hs:12:20-29,AnnDcolon), [Test11321.hs:12:23-24]),
((Test11321.hs:12:20-29,AnnOpenP), [Test11321.hs:12:20]),
((Test11321.hs:12:21-28,AnnDcolon), [Test11321.hs:12:23-24]),
((Test11321.hs:12:26-28,AnnCloseS), [Test11321.hs:12:28]),
((Test11321.hs:12:26-28,AnnOpenS), [Test11321.hs:12:26]),
((Test11321.hs:(13,5)-(14,8),AnnDarrow), [Test11321.hs:13:13-14]),
......
T7938.hs:12:16: error:
• Expected a type, but ‘(KP :: KProxy k2)’ has kind ‘KProxy k4’
T7938.hs:12:17: error:
• Expected a type, but ‘KP :: KProxy k2’ has kind ‘KProxy k4’
• In the type ‘(KP :: KProxy k2)’
In the type instance declaration for ‘Bar’
In the instance declaration for ‘Foo (a :: k1) (b :: k2)’
......@@ -158,7 +158,7 @@
{OccName: Length}))
(HsQTvs
(NoExt)
[({ DumpParsedAst.hs:7:20-30 }
[({ DumpParsedAst.hs:7:21-29 }
(KindedTyVar
(NoExt)
({ DumpParsedAst.hs:7:21-22 }
......
......@@ -205,7 +205,7 @@
[{Name: k}]
{NameSet:
[]})
[({ DumpRenamedAst.hs:8:20-30 }
[({ DumpRenamedAst.hs:8:21-29 }
(KindedTyVar
(NoExt)
({ DumpRenamedAst.hs:8:21-22 }
......@@ -288,27 +288,30 @@
({ DumpRenamedAst.hs:15:18-20 }
{Name: DumpRenamedAst.Nat})
[({ DumpRenamedAst.hs:15:22-34 }
(HsKindSig
(HsParTy
(NoExt)
({ DumpRenamedAst.hs:15:23 }
(HsTyVar
({ DumpRenamedAst.hs:15:23-33 }
(HsKindSig
(NoExt)
(NotPromoted)
({ DumpRenamedAst.hs:15:23 }
{Name: a})))
({ DumpRenamedAst.hs:15:28-33 }
(HsFunTy
(NoExt)
({ DumpRenamedAst.hs:15:28 }
(HsTyVar
(NoExt)
(NotPromoted)
({ DumpRenamedAst.hs:15:28 }
{Name: k})))
({ DumpRenamedAst.hs:15:33 }
(HsStarTy
({ DumpRenamedAst.hs:15:23 }
{Name: a})))
({ DumpRenamedAst.hs:15:28-33 }
(HsFunTy
(NoExt)
(False)))))))]
({ DumpRenamedAst.hs:15:28 }
(HsTyVar
(NoExt)
(NotPromoted)
({ DumpRenamedAst.hs:15:28 }
{Name: k})))
({ DumpRenamedAst.hs:15:33 }
(HsStarTy
(NoExt)
(False)))))))))]
(Prefix)
(HsDataDefn
(NoExt)
......
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE UnboxedSums #-}
{-# LANGUAGE UnboxedTuples #-}
{-# LANGUAGE TypeFamilies #-}
module KindSigs where
import Data.Kind
-- Kind annotation on type family instance equation
type family Foo a where
Foo a = Int :: Type
-- Kind annotation on component of tuple type
type Bar a = ( Int :: Type, Bool, Maybe a :: Type )
type Bar' a = (# Int :: Type, Bool, Maybe a :: Type #)
-- Kind annotation on type of list
type Baz = [ Int :: Type ]
-- Kind annotation inside paren type
qux :: (Int :: Type) -> Bool -> (() :: Type)
qux _ _ = ()
-- Kind annotation on promoted lists and tuples
type Quux = '[ True :: Bool ]
type Quux' = [ True :: Bool, False :: Bool ]
type Quuux b = '( [Int, Bool] :: [Type], b )
-- Note that 'true :: Bool :: Type' won't parse - you need some parens
true :: (Bool :: Type)
true = True
This diff is collapsed.
{-# LANGUAGE TypeFamilies #-}
module T11622 where
import Data.Kind (Type)
type family F a where
F _ = Int :: Type
{-# LANGUAGE KindSignatures #-}
module T808 where
import Data.Kind (Type)
foo :: (Int, Int :: Type)
foo = undefined
......@@ -101,6 +101,7 @@ test('T7776', normal, compile, [''])
test('RdrNoStaticPointers01', [], compile, [''])
test('T5682', normal, compile, [''])
test('T8258', normal, compile, [''])
test('T8708', normal, compile, [''])
test('T9723a', normal, compile, [''])
test('T9723b', normal, compile, [''])
test('T10188', normal, compile, [''])
......@@ -108,6 +109,7 @@ test('VtaParse', normal, compile, [''])
test('T10196', normal, compile, [''])
test('T10379', normal, compile, [''])
test('T10582', expect_broken(10582), compile, [''])
test('T11622', normal, compile, [''])
test('DumpParsedAst', normal, compile, ['-dsuppress-uniques -ddump-parsed-ast'])
test('DumpRenamedAst', normal, compile, ['-dsuppress-uniques -ddump-rn-ast'])
test('DumpTypecheckedAst', normal, compile, ['-dsuppress-uniques -ddump-tc-ast'])
......@@ -117,6 +119,8 @@ test('T13986', normal, compile, [''])
test('T10855', normal, compile, [''])
test('T15139', normal, compile, ['-Wincomplete-patterns -fdiagnostics-show-caret'])
test('T15323', normal, compile, ['-dsuppress-uniques -ddump-parsed-ast'])
test('KindSigs', normal, compile, ['-dsuppress-uniques -ddump-parsed-ast'])
def only_MG_loc(x):
"""
......
T14450.hs:33:12: error:
T14450.hs:33:13: error:
• Expected kind ‘k ~> k’,
but ‘(IddSym0 :: Type ~> Type)’ has kind ‘* ~> *’
but ‘IddSym0 :: Type ~> Type’ has kind ‘* ~> *’
• In the first argument of ‘Dom’, namely
‘(IddSym0 :: Type ~> Type)’
In the type instance declaration for ‘Dom’
......
T14580.hs:8:31: error:
• Expected kind ‘Cat a’, but ‘(iso :: cat a b)’ has kind ‘cat a b’
T14580.hs:8:32: error:
• Expected kind ‘Cat a’, but ‘iso :: cat a b’ has kind ‘cat a b’
• In the first argument of ‘ISO’, namely ‘(iso :: cat a b)’
In the type ‘ISO (iso :: cat a b)’
In the type declaration for ‘<-->’
T15629.hs:26:34: error:
T15629.hs:26:35: error:
• Expected kind ‘x1 ~> F x1 ab1’,
but ‘(F1Sym :: x ~> F x z)’ has kind ‘x1 ~> F x1 z’
but ‘F1Sym :: x ~> F x z’ has kind ‘x1 ~> F x1 z’
• In the first argument of ‘Comp’, namely ‘(F1Sym :: x ~> F x z)’
In the first argument of ‘Proxy’, namely
‘((Comp (F1Sym :: x ~> F x z) F2Sym) :: F x ab ~> F x ab)’
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment