@@ -15,7 +15,9 @@ import Text.PrettyPrint as P
1515
1616mistakes :: (Data t, Data v) => [Declaration t v] -> [Doc]
1717mistakes decls =
18− illFormedTypes decls ++ map P.text (concatMap findErrors (getLets decls))
18+ concat [ infiniteTypeAliases decls
19+ , illFormedTypes decls
20+ , map P.text (concatMap findErrors (getLets decls)) ]
1921 where
2022 findErrors defs = duplicates defs ++ badOrder defs
2123
@@ -104,4 +106,37 @@ illFormedTypes decls = map report (Maybe.mapMaybe isIllFormed (aliases ++ adts))
104106 | length xs < 2 = xs
105107 | otherwise = zipWith (++) (replicate (length xs - 1) "" ++ ["and "]) xs
106108
107− quote tvar = "'" ++ tvar ++ "'"
109+ quote tvar = "'" ++ tvar ++ "'"
110+
111+
112+infiniteTypeAliases :: [Declaration t v] -> [Doc]
113+infiniteTypeAliases decls =
114+ [ report decl | decl@(TypeAlias name _ tipe) <- decls, isInfinite name tipe ]
115+ where
116+ isInfinite name tipe =
117+ let infinite = isInfinite name in
118+ case tipe of
119+ T.Lambda a b -> infinite a || infinite b
120+ T.Var _ -> False
121+ T.Data name' ts -> name == name' || any infinite ts
122+ T.EmptyRecord -> False
123+ T.Record fields ext -> infinite ext || any (infinite . snd) fields
124+
125+ report decl@(TypeAlias name args tipe) =
126+ P.vcat [ P.text $ eightyCharLines 0 msg1
127+ , indented decl
128+ , P.text $ eightyCharLines 0 msg2
129+ , indented (Datatype name args [(name,[tipe])])
130+ , P.text $ eightyCharLines 0 msg3 ++ "\n"
131+ ]
132+ where
133+ indented decl = P.text "\n " <> pretty decl <> P.text "\n"
134+
135+ msg1 = "Type alias '" ++ name ++ "' is an infinite type. " ++
136+ "Notice that it appears in its own definition, so when \
137+ \you expand it, it just keeps getting bigger:"
138+ msg2 = "Try this instead:"
139+ msg3 = "It looks very similar, but an algebraic data type (ADT) \
140+ \actually creates a new type. Unlike with a type alias, this \
141+ \freshly created type is meaningful on its own, so an ADT \
142+ \does not need to be expanded."