@@ -20,8 +20,10 @@ module Reporting.Error.Type
2020
2121
2222import Prelude hiding (round)
23+import qualified Data.Map as Map
2324import Data.Monoid ((<>))
2425
26+import qualified AST.Canonical as Can
2527import qualified Data.Index as Index
2628import qualified Elm.Name as N
2729import qualified Reporting.Doc as D
@@ -63,9 +65,8 @@ data Context
6365 | CaseBranch Index.ZeroBased
6466 | CallArity MaybeName Int
6567 | CallArg MaybeName Index.ZeroBased
66− | TooManyArgs MaybeName Int
6768 | RecordAccess N.Name
68− | RecordUpdate
69+ | RecordUpdate N.Name (Map.Map N.Name Can.Expr)
6970 | Destructure
7071
7172
@@ -185,36 +186,26 @@ toPatternReport source localizer patternRegion category tipe expected =
185186 case expected of
186187 PNoExpectation expectedType ->
187188 Report.toCodeSnippet source patternRegion Nothing $
188− (
189− "This pattern is being used in an unexpected way:"
190− ,
191− patternTypeComparison localizer tipe expectedType
192− (
193− toPatternDescription category "It is"
194− ,
195− "But it needs to match values of type:"
196− ,
197− []
198− )
189+ ( "This pattern is being used in an unexpected way:"
190+ , patternTypeComparison localizer tipe expectedType
191+ (addPatternCategory "It is" category)
192+ (singular "But it needs to match")
193+ []
199194 )
200195
201196 PFromContext region context expectedType ->
202197 Report.toCodeSnippet source region (Just patternRegion) $
203198 case context of
204199 PTypedArg name index ->
205− (
206− D.reflow $
207− "The " <> D.ordinalize (Index.toHuman index) <> " argument to `" <> N.toString name <> "` is weird."
208− ,
209− patternTypeComparison localizer tipe expectedType
210− (
211− toPatternDescription category $
212− "The argument is a pattern that matches"
213− ,
214− "But the type annotation on `" <> N.toString name <> "` says the " <> D.ordinalize (Index.toHuman index) <> " argument should be:"
215− ,
216− []
200+ ( D.reflow $
201+ "The " <> D.ordinal index <> " argument to `" <> N.toString name <> "` is weird."
202+ , patternTypeComparison localizer tipe expectedType
203+ (addPatternCategory "The argument is a pattern that matches" category)
204+ (singular $
205+ "But the type annotation on `" <> N.toString name
206+ <> "` says the " <> D.ordinal index <> " argument should be"
217207 )
208+ []
218209 )
219210
220211 PCaseMatch index ->
@@ -224,82 +215,58 @@ toPatternReport source localizer patternRegion category tipe expected =
224215 "The 1st pattern in this `case` causing a mismatch:"
225216 ,
226217 patternTypeComparison localizer tipe expectedType
227− (
228− toPatternDescription category "The first pattern is trying to match"
229− ,
230− "But it is supposed to match an expression of type:"
231− ,
232− [ D.reflow $
233− "Is the pattern the problem? Or is it the expression you are trying to match on?"
234− ]
235− )
218+ (addPatternCategory "The first pattern is trying to match" category)
219+ (singular "But the expression between `case` and `of` is")
220+ [ D.reflow $
221+ "These can never match! Is the pattern the problem? Or is it the expression?"
222+ ]
236223 )
237224 else
238− (
239− D.reflow $
240− "The " <> D.ordinalize (Index.toHuman index) <> " pattern in this `case` does not match the previous ones."
241− ,
242− patternTypeComparison localizer tipe expectedType
243− (
244− toPatternDescription category $
245− "The " <> D.ordinalize (Index.toHuman index) <> " pattern is trying to match"
246− ,
247− "But all the previous patterns match values of type:"
248− ,
249− []
250− )
225+ ( D.reflow $
226+ "The " <> D.ordinal index <> " pattern in this `case` does not match the previous ones."
227+ , patternTypeComparison localizer tipe expectedType
228+ (addPatternCategory ("The " <> D.ordinal index <> " pattern is trying to match") category)
229+ (plural "But all the previous patterns match")
230+ [ D.link "Note"
231+ "A `case` expression can only handle one type of value, so you may want to use"
232+ "union-types"
233+ "to handle “mixing” types."
234+ ]
251235 )
252236
253237 PCtorArg name index ->
254− (
255− D.reflow $
256− "The " <> D.ordinalize (Index.toHuman index) <> " argument to `" <> N.toString name <> "` is weird."
257− ,
258− patternTypeComparison localizer tipe expectedType
259− (
260− toPatternDescription category "It is trying to match"
261− ,
262− "But `" <> N.toString name <> "` needs its " <> D.ordinalize (Index.toHuman index) <> " argument to be:"
263− ,
264− []
238+ ( D.reflow $
239+ "The " <> D.ordinal index <> " argument to `" <> N.toString name <> "` is weird."
240+ , patternTypeComparison localizer tipe expectedType
241+ (addPatternCategory "It is trying to match" category)
242+ (singular $
243+ "But `" <> N.toString name <> "` needs its "
244+ <> D.ordinal index <> " argument to be"
265245 )
246+ []
266247 )
267248
268249 PListEntry index ->
269− (
270− D.reflow $
271− "The " <> D.ordinalize (Index.toHuman index) <> " pattern in this list does not match all the previous ones:"
272− ,
273− patternTypeComparison localizer tipe expectedType
274− (
275− toPatternDescription category $
276− "The " <> D.ordinalize (Index.toHuman index) <> " pattern is trying to match"
277− ,
278− "But all the previous patterns in the list are:"
279− ,
280− [ D.toSimpleHint $
281− "Everything in the list needs to be the same type of value.\
282− \ This way you never run into unexpected values partway through.\
283− \ To mix different types in a single list, create a \"union type\" as\
284− \ described in: <http://guide.elm-lang.org/types/union_types.html>"
285− ]
286− )
250+ ( D.reflow $
251+ "The " <> D.ordinal index <> " pattern in this list does not match all the previous ones:"
252+ , patternTypeComparison localizer tipe expectedType
253+ (addPatternCategory ("The " <> D.ordinal index <> " pattern is trying to match") category)
254+ (plural "But all the previous patterns in the list are")
255+ [ D.toSimpleHint $
256+ "Everything in the list needs to be the same type of value.\
257+ \ This way you never run into unexpected values partway through.\
258+ \ To mix different types in a single list, create a \"union type\" as\
259+ \ described in: <http://guide.elm-lang.org/types/union_types.html>"
260+ ]
287261 )
288262
289263 PTail ->
290− (
291− D.reflow $
264+ ( D.reflow $
292265 "The pattern after (::) is causing issues."
293− ,
294− patternTypeComparison localizer tipe expectedType
295− (
296− toPatternDescription category $
297− "The pattern after (::) is trying to match"
298− ,
299− "But it needs to match lists like this:"
300− ,
301− []
302− )
266+ , patternTypeComparison localizer tipe expectedType
267+ (addPatternCategory "The pattern after (::) is trying to match" category)
268+ (\_ -> "But it needs to match lists like this:")
269+ []
303270 )
304271
305272
@@ -307,96 +274,144 @@ toPatternReport source localizer patternRegion category tipe expected =
307274-- PATTERN HELPERS
308275
309276
310−patternTypeComparison :: L.Localizer -> T.Type -> T.Type -> ( String, String, [D.Doc] ) -> D.Doc
311−patternTypeComparison localizer actual expected ( iAmSeeing, insteadOf, contextHints ) =
277+patternTypeComparison
278+ :: L.Localizer
279+ -> T.Type
280+ -> T.Type
281+ -> (Maybe N.Name -> D.Doc)
282+ -> (Maybe N.Name -> D.Doc)
283+ -> [D.Doc]
284+ -> D.Doc
285+patternTypeComparison localizer actual expected iAmSeeing insteadOf contextHints =
312286 let
313− (actualDoc, expectedDoc, problems) =
314− T.toDiffDocs localizer actual expected
287+ (T.Comparison actualAlias actualDoc expectedAlias expectedDoc problems) =
288+ T.toComparison localizer actual expected
315289 in
316290 D.stack $
317− [ D.reflow iAmSeeing
291+ [ iAmSeeing actualAlias
318292 , D.indent 4 actualDoc
319− , D.reflow insteadOf
293+ , insteadOf expectedAlias
320294 , D.indent 4 expectedDoc
321295 ]
322296 ++ problemsToHint problems
323297 ++ contextHints
324298
325299
326−toPatternDescription :: PCategory -> String -> String
327−toPatternDescription category iAmTryingToMatch =
328− iAmTryingToMatch <>
329− case category of
330− PRecord -> " record values of type:"
331− PUnit -> " unit values:"
332− PTuple -> " tuples of type:"
333− PList -> " lists of type:"
334− PCtor name -> " `" <> N.toString name <> "` values of type:"
335− PInt -> " integers:"
336− PStr -> " strings:"
337− PChr -> " characters:"
300+addPatternCategory :: String -> PCategory -> Maybe N.Name -> D.Doc
301+addPatternCategory iAmTryingToMatch category maybeAlias =
302+ D.reflow $ iAmTryingToMatch <>
303+ case maybeAlias of
304+ Just alias ->
305+ " `" <> N.toString alias <> "` values:"
306+
307+ Nothing ->
308+ case category of
309+ PRecord -> " record values of type:"
310+ PUnit -> " unit values:"
311+ PTuple -> " tuples of type:"
312+ PList -> " lists of type:"
313+ PCtor name -> " `" <> N.toString name <> "` values of type:"
314+ PInt -> " integers:"
315+ PStr -> " strings:"
316+ PChr -> " characters:"
338317
339318
340319
341320-- EXPR HELPERS
342321
343322
344−typeComparison :: L.Localizer -> T.Type -> T.Type -> ( String, String, [D.Doc] ) -> D.Doc
345−typeComparison localizer actual expected ( iAmSeeing, insteadOf, contextHints ) =
323+typeComparison
324+ :: L.Localizer
325+ -> T.Type
326+ -> T.Type
327+ -> (Maybe N.Name -> D.Doc)
328+ -> (Maybe N.Name -> D.Doc)
329+ -> [D.Doc]
330+ -> D.Doc
331+typeComparison localizer actual expected iAmSeeing insteadOf contextHints =
346332 let
347− (actualDoc, expectedDoc, problems) =
348− T.toDiffDocs localizer actual expected
333+ (T.Comparison actualAlias actualDoc expectedAlias expectedDoc problems) =
334+ T.toComparison localizer actual expected
349335 in
350336 D.stack $
351− [ D.reflow iAmSeeing
337+ [ iAmSeeing actualAlias
352338 , D.indent 4 actualDoc
353− , D.reflow insteadOf
339+ , insteadOf expectedAlias
354340 , D.indent 4 expectedDoc
355341 ]
356342 ++ problemsToHint problems
357343 ++ contextHints
358344
359345
360−loneType :: L.Localizer -> T.Type -> T.Type -> ( D.Doc, [D.Doc] ) -> D.Doc
361−loneType localizer actual expected ( iAmSeeing, furtherDetails ) =
346+loneType
347+ :: L.Localizer
348+ -> T.Type
349+ -> T.Type
350+ -> (Maybe N.Name -> D.Doc)
351+ -> [D.Doc]
352+ -> D.Doc
353+loneType localizer actual expected iAmSeeing furtherDetails =
362354 let
363− (actualDoc, _, problems) =
364− T.toDiffDocs localizer actual expected
355+ (T.Comparison actualAlias actualDoc _ _ problems) =
356+ T.toComparison localizer actual expected
365357 in
366358 D.stack $
367− [ iAmSeeing
359+ [ iAmSeeing actualAlias
368360 , D.indent 4 actualDoc
369361 ]
370362 ++ furtherDetails
371363 ++ problemsToHint problems
372364
373365
374−toDescription :: Category -> String -> String
375−toDescription category thatThingIs =
366+singular :: String -> Maybe N.Name -> D.Doc
367+singular insteadOf maybeAlias =
368+ D.reflow $ insteadOf <>
369+ case maybeAlias of
370+ Nothing -> ":"
371+ Just a -> " a `" <> N.toString a <> "` value:"
372+
373+
374+plural :: String -> Maybe N.Name -> D.Doc
375+plural insteadOf maybeAlias =
376+ D.reflow $ insteadOf <>
377+ case maybeAlias of
378+ Nothing -> ":"
379+ Just a -> " `" <> N.toString a <> "` values:"
380+
381+
382+addCategory :: String -> Category -> Maybe N.Name -> D.Doc
383+addCategory thisIs category maybeAlias =
384+ let
385+ definitely whatever =
386+ case maybeAlias of
387+ Just alias -> " a `" <> N.toString alias <> "` value:"
388+ Nothing -> whatever
389+ in
390+ D.reflow $
376391 case category of
377− Local name -> "This `" <> N.toString name <> "` value has type:"
378− Foreign name -> "This `" <> N.toString name <> "` value has type:"
379− Access field -> "The value at ." <> N.toString field <> " has type:"
392+ Local name -> "This `" <> N.toString name <> "` value is" <> definitely " a:"
393+ Foreign name -> "This `" <> N.toString name <> "` value is" <> definitely " a:"
394+ Access field -> "The value at ." <> N.toString field <> " is" <> definitely " a:"
380395 Accessor field -> "This ." <> N.toString field <> " field access function has type:"
381− If -> "This `if` expression produces a value of type:"
382− Case -> "This `case` expression produces a value of type:"
383− List -> thatThingIs <> " a list of type:"
384− Number -> thatThingIs <> " a number of type:"
385− Float -> thatThingIs <> " a float of type:"
386− String -> thatThingIs <> " a string of type:"
387− Char -> thatThingIs <> " a character of type:"
388− Lambda -> thatThingIs <> " an anonymous function of type:"
389− Record -> thatThingIs <> " a record of type:"
390− Tuple -> thatThingIs <> " a tuple of type:"
391− Unit -> thatThingIs <> " a unit value:"
392− Shader -> thatThingIs <> " a GLSL shader of type:"
393− Effects -> thatThingIs <> " a thing for CORE LIBRARIES ONLY."
396+ If -> "This `if` expression produces" <> definitely ":"
397+ Case -> "This `case` expression produces" <> definitely ":"
398+ List -> thisIs <> definitely " a list of type:"
399+ Number -> thisIs <> definitely " a number of type:"
400+ Float -> thisIs <> definitely " a float of type:"
401+ String -> thisIs <> definitely " a string of type:"
402+ Char -> thisIs <> definitely " a character of type:"
403+ Lambda -> thisIs <> definitely " an anonymous function of type:"
404+ Record -> thisIs <> definitely " a record of type:"
405+ Tuple -> thisIs <> definitely " a tuple of type:"
406+ Unit -> thisIs <> definitely " a unit value:"
407+ Shader -> thisIs <> definitely " a GLSL shader of type:"
408+ Effects -> thisIs <> " a thing for CORE LIBRARIES ONLY."
394409 CallResult maybeName ->
395410 case maybeName of
396− NoName -> thatThingIs <> ":"
397− FuncName name -> "This `" <> N.toString name <> "` call produces:"
398− CtorName name -> "This `" <> N.toString name <> "` call produces:"
399− OpName _ -> thatThingIs <> ":"
411+ NoName -> thisIs <> ":"
412+ FuncName name -> "This `" <> N.toString name <> "` call produces" <> definitely ":"
413+ CtorName name -> "This `" <> N.toString name <> "` call produces" <> definitely ":"
414+ OpName _ -> thisIs <> definitely ":"
400415
401416
402417problemsToHint :: [T.Problem] -> [D.Doc]
@@ -637,203 +652,171 @@ badFlexFlexSuper s1 s2 =
637652
638653toExprReport :: Code.Source -> L.Localizer -> R.Region -> Category -> T.Type -> Expected T.Type -> Report.Report
639654toExprReport source localizer exprRegion category tipe expected =
640− Report.Report "TYPE MISMATCH" exprRegion [] $
641655 case expected of
642656 NoExpectation expectedType ->
643− Report.toCodeSnippet source exprRegion Nothing
644− (
645− "This expression is being used in an unexpected way:"
646− ,
647− typeComparison localizer tipe expectedType
648− (
649− toDescription category "It is"
650− ,
651− "But you are trying to use it as:"
652− ,
657+ Report.Report "TYPE MISMATCH" exprRegion [] $
658+ Report.toCodeSnippet source exprRegion Nothing
659+ ( "This expression is being used in an unexpected way:"
660+ , typeComparison localizer tipe expectedType
661+ (addCategory "It is" category)
662+ (singular "But you are trying to use it as")
653663 []
654− )
655− )
664+ )
656665
657666 FromAnnotation name _arity subContext expectedType ->
658− Report.toCodeSnippet source exprRegion Nothing
659− (
660− D.reflow $
661− case subContext of
662− TypedIfBranch index ->
663− "Something is off with the " <> D.ordinalize (Index.toHuman index) <> " branch of this `if` expression:"
664−
665− TypedCaseBranch index ->
666− "Something is off with the " <> D.ordinalize (Index.toHuman index) <> " branch of this `case` expression:"
667−
668− TypedBody ->
669− "Something is off with the body of the `" <> N.toString name <> "` definition:"
670− ,
671− typeComparison localizer tipe expectedType
672− (
673− toDescription category $
674− case subContext of
675− TypedIfBranch index ->
676− "The " <> D.ordinalize (Index.toHuman index) <> " branch is"
677−
678− TypedCaseBranch index ->
679− "The " <> D.ordinalize (Index.toHuman index) <> " branch is"
680−
681− TypedBody ->
682− "The body is"
683− ,
684− "But the type annotation on `" <> N.toString name <> "` says it should be:"
685− ,
667+ let
668+ thing =
669+ case subContext of
670+ TypedIfBranch index -> D.ordinal index <> " branch of this `if` expression:"
671+ TypedCaseBranch index -> D.ordinal index <> " branch of this `case` expression:"
672+ TypedBody -> "body of the `" <> N.toString name <> "` definition:"
673+
674+ itIs =
675+ case subContext of
676+ TypedIfBranch index -> "The " <> D.ordinal index <> " branch is"
677+ TypedCaseBranch index -> "The " <> D.ordinal index <> " branch is"
678+ TypedBody -> "The body is"
679+ in
680+ Report.Report "TYPE MISMATCH" exprRegion [] $
681+ Report.toCodeSnippet source exprRegion Nothing $
682+ ( D.reflow ("Something is off with the " <> thing)
683+ , typeComparison localizer tipe expectedType
684+ (addCategory itIs category)
685+ (singular $ "But the type annotation on `" <> N.toString name <> "` says it should be")
686686 []
687− )
688− )
687+ )
689688
690689 FromContext region context expectedType ->
690+ let
691+ mismatch (maybeHighlight, problem, thisIs, insteadOf, furtherDetails) =
692+ Report.Report "TYPE MISMATCH" exprRegion [] $
693+ Report.toCodeSnippet source region maybeHighlight
694+ ( D.reflow problem
695+ , typeComparison localizer tipe expectedType (addCategory thisIs category) insteadOf furtherDetails
696+ )
697+
698+ badType (maybeHighlight, problem, thisIs, furtherDetails) =
699+ Report.Report "TYPE MISMATCH" exprRegion [] $
700+ Report.toCodeSnippet source region maybeHighlight
701+ ( D.reflow problem
702+ , loneType localizer tipe expectedType (addCategory thisIs category) furtherDetails
703+ )
704+ in
691705 case context of
692706 ListEntry index ->
693− Report.toCodeSnippet source region (Just exprRegion)
694− (
695− D.reflow $
696− "The " <> D.ordinalize (Index.toHuman index) <> " element of this list does not match all the previous elements:"
697− ,
698− typeComparison localizer tipe expectedType
699− (
700− toDescription category $
701− "The " <> D.ordinalize (Index.toHuman index) <> " element is"
702− ,
703− "But all the previous elements in the list are:"
704− ,
705− [ D.toSimpleHint $
706− "Everything in the list needs to be the same type of value.\
707− \ This way you never run into unexpected values partway through.\
708− \ To mix different types in a single list, create a \"union type\" as\
709− \ described in: <http://guide.elm-lang.org/types/union_types.html>"
710− ]
711− )
712− )
707+ let ith = D.ordinal index in
708+ mismatch
709+ ( Just exprRegion
710+ , "The " <> ith <> " element of this list does not match all the previous elements:"
711+ , "The " <> ith <> " element is"
712+ , plural "But all the previous elements in the list are"
713+ , [ D.toSimpleHint $
714+ "Everything in the list needs to be the same type of value.\
715+ \ This way you never run into unexpected values partway through.\
716+ \ To mix different types in a single list, create a \"union type\" as\
717+ \ described in: <http://guide.elm-lang.org/types/union_types.html>"
718+ ]
719+ )
713720
714721 Negate ->
715− Report.toCodeSnippet source region (Just exprRegion)
716− (
717− "I do not know how to negate this type of value:"
718− ,
719− loneType localizer tipe expectedType
720− (
721− D.reflow $ toDescription category "It is"
722− ,
723− [ D.fillSep
724− ["But","I","only","now","how","to","negate"
725− ,D.dullyellow "Int","and",D.dullyellow "Float","values."
726− ]
727− ]
728− )
729− )
722+ badType
723+ ( Just exprRegion
724+ , "I do not know how to negate this type of value:"
725+ , "It is"
726+ , [ D.fillSep
727+ ["But","I","only","now","how","to","negate"
728+ ,D.dullyellow "Int","and",D.dullyellow "Float","values."
729+ ]
730+ ]
731+ )
730732
731733 OpLeft op ->
732− Report.toCodeSnippet source region (Just exprRegion) $
733− opLeftToDocs localizer category op tipe expectedType
734+ Report.Report "TYPE MISMATCH" exprRegion [] $
735+ Report.toCodeSnippet source region (Just exprRegion) $
736+ opLeftToDocs localizer category op tipe expectedType
734737
735738 OpRight op ->
736− case opRightToDocs localizer category op tipe expectedType of
737− EmphBoth details ->
738− Report.toCodeSnippet source region Nothing details
739+ Report.Report "TYPE MISMATCH" exprRegion [] $
740+ case opRightToDocs localizer category op tipe expectedType of
741+ EmphBoth details ->
742+ Report.toCodeSnippet source region Nothing details
739743
740− EmphRight details ->
741− Report.toCodeSnippet source region (Just exprRegion) details
744+ EmphRight details ->
745+ Report.toCodeSnippet source region (Just exprRegion) details
742746
743747 IfCondition ->
744− Report.toCodeSnippet source region (Just exprRegion)
745− (
746− "This `if` condition does not evaluate to a boolean value, True or False."
747− ,
748− loneType localizer tipe expectedType
749− (
750− D.reflow $ toDescription category "It is"
751− ,
752− [ D.fillSep ["But","I","need","this","`if`","condition","to","be","a",D.dullyellow "Bool","value."]
753− ]
754− )
755− )
748+ badType
749+ ( Just exprRegion
750+ , "This `if` condition does not evaluate to a boolean value, True or False."
751+ , "It is"
752+ , [ D.fillSep ["But","I","need","this","`if`","condition","to","be","a",D.dullyellow "Bool","value."]
753+ ]
754+ )
756755
757756 IfBranch index ->
758− Report.toCodeSnippet source region (Just exprRegion)
759− (
760− D.reflow $
761− "The " <> D.ordinalize (Index.toHuman index) <> " branch of this `if` does not match all the previous branches:"
762− ,
763− typeComparison localizer tipe expectedType
764− (
765− toDescription category $
766− "The " <> D.ordinalize (Index.toHuman index) <> " branch is"
767− ,
768− "But all the previous branches result in:"
769− ,
770− [ D.link "Hint"
771− "All branches in an `if` must produce the same type of values. This way, no\
772− \ matter which branch we take, the result is always a consistent shape. Read"
773− "union-types"
774− "to learn how to “mix” types."
775− ]
776− )
777− )
757+ let ith = D.ordinal index in
758+ mismatch
759+ ( Just exprRegion
760+ , "The " <> ith <> " branch of this `if` does not match all the previous branches:"
761+ , "The " <> ith <> " branch is"
762+ , plural "But all the previous branches result in"
763+ , [ D.link "Hint"
764+ "All branches in an `if` must produce the same type of values. This way, no\
765+ \ matter which branch we take, the result is always a consistent shape. Read"
766+ "union-types"
767+ "to learn how to “mix” types."
768+ ]
769+ )
778770
779771 CaseBranch index ->
780− Report.toCodeSnippet source region (Just exprRegion)
781− (
782− D.reflow $
783− "The " <> D.ordinalize (Index.toHuman index) <> " branch of this `case` does not match all the previous branches:"
784− ,
785− typeComparison localizer tipe expectedType
786− (
787− toDescription category $
788− "The " <> D.ordinalize (Index.toHuman index) <> " branch is"
789− ,
790− "But all the previous branches result in:"
791− ,
792− [ D.link "Hint"
793− "All branches in a `case` must produce the same type of values. This way, no\
794− \ matter which branch we take, the result is always a consistent shape. Read"
795− "union-types"
796− "to learn how to “mix” types."
797− ]
798− )
799− )
772+ let ith = D.ordinal index in
773+ mismatch
774+ ( Just exprRegion
775+ , "The " <> ith <> " branch of this `case` does not match all the previous branches:"
776+ , "The " <> ith <> " branch is"
777+ , plural "But all the previous branches result in"
778+ , [ D.link "Hint"
779+ "All branches in a `case` must produce the same type of values. This way, no\
780+ \ matter which branch we take, the result is always a consistent shape. Read"
781+ "union-types"
782+ "to learn how to “mix” types."
783+ ]
784+ )
800785
801− CallArity maybeFuncName numArgs ->
786+ CallArity maybeFuncName numGivenArgs ->
787+ Report.Report "TOO MANY ARGS" exprRegion [] $
788+ Report.toCodeSnippet source region (Just exprRegion) $
802789 case countArgs tipe of
803790 0 ->
804− Report.toCodeSnippet source region (Just exprRegion)
805− ( D.reflow $
806− case maybeFuncName of
807− NoName -> "This is not a function:"
808− FuncName name -> "The `" <> N.toString name <> "` value is not a function:"
809− CtorName name -> "The `" <> N.toString name <> "` value is not a function:"
810− OpName op -> "The (" <> N.toString op <> ") operator is not a function:"
811− ,
812− D.stack $
813− [ "It has type:"
814− , D.indent 4 $ D.dullyellow $ T.toDoc localizer RT.None tipe
815− , D.reflow $ "So it cannot accept arguments, but it got " <> show numArgs <> " anyway."
816− ]
817− )
791+ let
792+ thisValue =
793+ case maybeFuncName of
794+ NoName -> "This value"
795+ FuncName name -> "The `" <> N.toString name <> "` value"
796+ CtorName name -> "The `" <> N.toString name <> "` value"
797+ OpName op -> "The (" <> N.toString op <> ") operator"
798+ in
799+ ( D.reflow $ thisValue <> " is not a function, but it was given " <> D.args numGivenArgs <> "."
800+ , D.reflow $ "Are there any missing commas? Or missing parentheses?"
801+ )
818802
819803 n ->
820− Report.toCodeSnippet source region (Just exprRegion)
821− ( D.reflow $
822− case maybeFuncName of
823− NoName -> "This function was given too many arguments:"
824− FuncName name -> "The `" <> N.toString name <> "` function was given too many arguments:"
825− CtorName name -> "The `" <> N.toString name <> "` constructor was given too many arguments:"
826− OpName op -> "The (" <> N.toString op <> ") operator was given too many arguments:"
827− ,
828− D.stack $
829− [ "It has type:"
830− , D.indent 4 $ D.dullyellow $ T.toDoc localizer RT.None tipe
831− , D.reflow $ "So it expects " <> D.args n <> ", but it got " <> show numArgs <> " instead."
832− ]
833− )
804+ let
805+ thisFunction =
806+ case maybeFuncName of
807+ NoName -> "This function"
808+ FuncName name -> "The `" <> N.toString name <> "` function"
809+ CtorName name -> "The `" <> N.toString name <> "` constructor"
810+ OpName op -> "The (" <> N.toString op <> ") operator"
811+ in
812+ ( D.reflow $ thisFunction <> " expects " <> D.args n <> ", but it got " <> show numGivenArgs <> " instead."
813+ , D.reflow $ "Are there any missing commas? Or missing parentheses?"
814+ )
834815
835816 CallArg maybeFuncName index ->
836817 let
818+ ith = D.ordinal index
819+
837820 thisFunction =
838821 case maybeFuncName of
839822 NoName -> "this function"
@@ -841,187 +824,81 @@ toExprReport source localizer exprRegion category tipe expected =
841824 CtorName name -> "`" <> N.toString name <> "`"
842825 OpName op -> "(" <> N.toString op <> ")"
843826 in
844− Report.toCodeSnippet source region (Just exprRegion)
845− (
846− D.reflow $
847− "The " <> D.ordinalize (Index.toHuman index) <> " argument to " <> thisFunction <> " is not what I expect:"
848− ,
849− typeComparison localizer tipe expectedType
850− (
851− toDescription category "This argument is"
852− ,
853− "But " <> thisFunction <> " needs the " <> D.ordinalize (Index.toHuman index)
854− <> " argument to be:"
855− ,
856− if Index.toHuman index == 1 then
857− []
858− else
859− [ D.toSimpleHint $
860− "I always figure out the argument types from left to right. If an argument\
861− \ is acceptable, I assume it is “correct” and move on. So the problem may\
862− \ actually be in one of the previous arguments!"
863− ]
864− )
865− )
866−
867− TooManyArgs maybeName numGivenArgs ->
868− case countArgs tipe of
869− 0 ->
870− Report.toCodeSnippet source region (Just exprRegion)
871− (
872− D.reflow $
873− case maybeName of
874− NoName ->
875− "You are giving " <> D.args numGivenArgs <> " to something that is not a function!"
876−
877− FuncName name ->
878− "`" <> N.toString name <> "` is not a function, but you are giving it " <> D.args numGivenArgs <> "!"
879−
880− CtorName name ->
881− "`" <> N.toString name <> "` is not a function, but you are giving it " <> D.args numGivenArgs <> "!"
882−
883− OpName op ->
884− "(" <> N.toString op <> ") is not a function, but you are giving it " <> D.args numGivenArgs <> "!"
885− ,
886− typeComparison localizer tipe expectedType
887− (
888− case maybeName of
889− NoName ->
890− "It is a value of type:"
891−
892− FuncName name ->
893− "`" <> N.toString name <> "` is a value of type:"
894−
895− CtorName name ->
896− "`" <> N.toString name <> "` is a constructor of type:"
897−
898− OpName op ->
899− "(" <> N.toString op <> ") is a value of type:"
900− ,
901− "But you are giving it " <> D.args numGivenArgs <> " as if its type was:"
902− ,
903− [ "Maybe you forgot some parentheses? Or a comma?"
904− ]
905− )
906− )
907−
908− numExpectedArgs ->
909− let
910− thisFunction =
911− case maybeName of
912− NoName ->
913− "This function"
914−
915− FuncName name ->
916− "The `" <> N.toString name <> "` function"
917−
918− CtorName name ->
919− "The `" <> N.toString name <> "` constructor"
920−
921− OpName op ->
922− "The (" <> N.toString op <> ") function"
923− in
924− Report.toCodeSnippet source region (Just exprRegion)
925− (
926− D.reflow $
927− thisFunction <> " is getting too many arguments:"
928− ,
929− typeComparison localizer tipe expectedType
930− (
931− thisFunction <> " is expecting to get " <> D.args numExpectedArgs <> " like this:"
932− ,
933− "But you are giving it " <> D.args numGivenArgs <> " as if its type was:"
934− ,
935− [ "Maybe you forgot some parentheses? Or a comma?"
936− , D.toSimpleNote $
937− "I am not good at figuring out which arguments are extra myself. The\
938− \ problem may even be that the FUNCTION is defined funny, and the arguments are\
939− \ actually fine. Anyway, I hope I gave enough info to help you figure it out!"
940− ]
941− )
942− )
827+ mismatch
828+ ( Just exprRegion
829+ , "The " <> ith <> " argument to " <> thisFunction <> " is not what I expect:"
830+ , "This argument is"
831+ , singular $ "But " <> thisFunction <> " needs the " <> ith <> " argument to be"
832+ ,
833+ if Index.toHuman index == 1 then
834+ []
835+ else
836+ [ D.toSimpleHint $
837+ "I always figure out the argument types from left to right. If an argument\
838+ \ is acceptable, I assume it is “correct” and move on. So the problem may\
839+ \ actually be in one of the previous arguments!"
840+ ]
841+ )
943842
944843 RecordAccess field ->
945− Report.toCodeSnippet source region (Just exprRegion) $
946− case tipe of
947− T.Record _ _ ->
948− (
949− D.reflow $
950− "This record does not have a `" <> N.toString field <> "` field:"
951− ,
952− loneType localizer tipe expectedType
953− (
954− D.reflow $ "It is a record with this type:"
955− ,
956− [ D.fillSep
957− ["Is","the",D.dullyellow ("." <> D.fromName field)
958− ,"field","access","is","misspelled?"
959− ]
960− ]
961− )
962− )
844+ badType $
845+ case T.getFields tipe of
846+ Just _fields ->
847+ ( Just exprRegion
848+ , "This record does not have a `" <> N.toString field <> "` field:"
849+ , "It is"
850+ , [ -- TODO suggest what the typo is!
851+ ]
852+ )
963853
964− _ ->
965− (
966− D.reflow $
967− "This is not a record, so it has no fields to access!"
968− ,
969− loneType localizer tipe expectedType
970− ( D.reflow $ toDescription category "It is"
971− , [ D.fillSep
972− ["But","I","need","a","record","with","a"
973− ,D.dullyellow (D.fromName field),"field!"
974− ]
975− ]
976− )
977− )
854+ Nothing ->
855+ ( Just exprRegion
856+ , "This is not a record, so it has no fields to access!"
857+ , "It is"
858+ , [ D.fillSep
859+ ["But","I","need","a","record","with","a"
860+ ,D.dullyellow (D.fromName field),"field!"
861+ ]
862+ ]
863+ )
978864
979− RecordUpdate ->
980− case T.iteratedDealias tipe of
981− T.Record _ _ ->
982− Report.toCodeSnippet source region Nothing $
983− (
984− D.reflow $
985− "I think there is a typo in one of these field names:"
986− ,
987− typeComparison localizer tipe expectedType
988− (
989− "The record you want to update has type:"
990− ,
991− "But you are saying it should have these fields:"
992− ,
993− [ D.reflow "Maybe there is some typo?"
994− ]
995− )
996− )
865+ RecordUpdate name updatedFields ->
866+ badType $
867+ case T.getFields tipe of
868+ Nothing ->
869+ ( Just exprRegion
870+ , "I cannot update the `" <> N.toString name <> "` value:"
871+ , "It is"
872+ , [ D.reflow $ "It is not a record. It has no fields to update!"
873+ ]
874+ )
997875
998− _ ->
999− Report.toCodeSnippet source region (Just exprRegion)
1000− (
1001− "The record update syntax does not work with this value:"
1002− ,
1003− loneType localizer tipe expectedType
1004− ( D.reflow $ toDescription category "It is"
1005− , [ D.reflow $ "But I need some kind of record here!"
1006− ]
1007− )
1008− )
876+ Just _fields ->
877+ case Map.keys updatedFields of
878+ [field] ->
879+ ( Nothing
880+ , "The `" <> N.toString name <> "` record does not have a `" <> N.toString field <> "` field."
881+ , "It is"
882+ , [ -- TODO suggest what the typo is!
883+ ]
884+ )
885+
886+ _ ->
887+ ( Nothing
888+ , "The `" <> N.toString name <> "` record does have all of these fields:"
889+ , "It is"
890+ , [ -- TODO suggest what the typo is!
891+ ]
892+ )
1009893
1010894 Destructure ->
1011− Report.toCodeSnippet source region Nothing
1012− (
1013− D.reflow $
1014− "I cannot destructure "
1015− ,
1016− typeComparison localizer tipe expectedType
1017− (
1018− toDescription category "You are defining"
1019− ,
1020− "But then trying to destructure it as:"
1021− ,
1022− []
1023− )
1024− )
895+ mismatch
896+ ( Nothing
897+ , "This definition is causing issues:"
898+ , "You are defining"
899+ , singular "But then trying to destructure it as"
900+ , []
901+ )
1025902
1026903
1027904
@@ -1069,27 +946,19 @@ opLeftToDocs localizer category op tipe expected =
1069946
1070947 "<|" ->
1071948 ( "The left side of (<|) needs to be a function so I can pipe arguments to it!"
1072− ,
1073− loneType localizer tipe expected
1074− ( D.reflow $ toDescription category "I am seeing"
1075− , [ D.reflow $ "This needs to be some kind of function though!"
1076− ]
1077− )
949+ , loneType localizer tipe expected
950+ (addCategory "I am seeing" category)
951+ [ D.reflow $ "This needs to be some kind of function though!"
952+ ]
1078953 )
1079954
1080955 _ ->
1081− (
1082− D.reflow $
956+ ( D.reflow $
1083957 "The left argument of (" <> N.toString op <> ") is causing problems:"
1084− ,
1085− typeComparison localizer tipe expected
1086− (
1087− toDescription category "The left argument is"
1088− ,
1089− "But (" <> N.toString op <> ") needs the left argument to be:"
1090− ,
1091− []
1092− )
958+ , typeComparison localizer tipe expected
959+ (addCategory "The left argument is" category)
960+ (singular $ "But (" <> N.toString op <> ") needs the left argument to be")
961+ []
1093962 )
1094963
1095964
@@ -1146,47 +1015,30 @@ opRightToDocs localizer category op tipe expected =
11461015
11471016 "<|" ->
11481017 EmphRight
1149− (
1150− D.reflow $
1151− "I cannot send this through the (<|) pipe:"
1152− ,
1153− typeComparison localizer tipe expected
1154− (
1155− toDescription category "You are providing"
1156− ,
1157− "But (<|) is piping it a function that expects:"
1158− ,
1159− []
1160− )
1018+ ( D.reflow $ "I cannot send this through the (<|) pipe:"
1019+ , typeComparison localizer tipe expected
1020+ (addCategory "You are providing" category)
1021+ (singular "But (<|) is piping it a function that expects")
1022+ []
11611023 )
11621024
11631025 "|>" ->
11641026 case (tipe, expected) of
11651027 (T.Lambda expectedArgType _ _, T.Lambda argType _ _) ->
11661028 EmphRight
1167− (
1168− "This function cannot handle the argument sent through the (|>) pipe:"
1169− ,
1170− typeComparison localizer argType expectedArgType
1171− (
1172− "You are providing an argument of type:"
1173− ,
1174− "But (|>) is piping it a function that expects its next argument to be:"
1175− ,
1176− []
1177− )
1029+ ( D.reflow $ "This function cannot handle the argument sent through the (|>) pipe:"
1030+ , typeComparison localizer argType expectedArgType
1031+ (addCategory "The argument is" category)
1032+ (singular "But (|>) is piping it a function that expects")
1033+ []
11781034 )
11791035
11801036 _ ->
11811037 EmphRight
1182− (
1183− "The right side of (|>) needs to be a function so I can pipe arguments to it!"
1184− ,
1185− loneType localizer tipe expected
1186− ( D.reflow $ toDescription category $
1187− "But instead of a function, I am seeing "
1188− , []
1189− )
1038+ ( D.reflow $ "The right side of (|>) needs to be a function so I can pipe arguments to it!"
1039+ , loneType localizer tipe expected
1040+ (addCategory "But instead of a function, I am seeing" category)
1041+ []
11901042 )
11911043
11921044 _ ->
@@ -1196,22 +1048,16 @@ opRightToDocs localizer category op tipe expected =
11961048badOpRightFallback :: L.Localizer -> Category -> N.Name -> T.Type -> T.Type -> RightDocs
11971049badOpRightFallback localizer category op tipe expected =
11981050 EmphRight
1199− (
1200− D.reflow $
1051+ ( D.reflow $
12011052 "The right argument of (" <> N.toString op <> ") is causing problems."
1202− ,
1203− typeComparison localizer tipe expected
1204− (
1205− toDescription category "The right argument is"
1206− ,
1207− "But (" <> N.toString op <> ") needs the right argument to be:"
1208− ,
1209− [ D.toSimpleHint $
1210− "With operators like (" ++ N.toString op ++ ") I always check the left\
1211− \ side first. If it seems fine, I assume it is correct and check the right\
1212− \ side. So the problem may be in how the left and right arguments interact!"
1213− ]
1214− )
1053+ , typeComparison localizer tipe expected
1054+ (addCategory "The right argument is" category)
1055+ (singular $ "But (" <> N.toString op <> ") needs the right argument to be")
1056+ [ D.toSimpleHint $
1057+ "With operators like (" ++ N.toString op ++ ") I always check the left\
1058+ \ side first. If it seems fine, I assume it is correct and check the right\
1059+ \ side. So the problem may be in how the left and right arguments interact!"
1060+ ]
12151061 )
12161062
12171063
@@ -1266,16 +1112,11 @@ badConsRight localizer category tipe expected =
12661112 case expected of
12671113 T.Type home2 name2 [expectedElement] | T.isList home2 name2 ->
12681114 EmphBoth
1269− (
1270− D.reflow "I am having trouble with this (::) operator:"
1271− ,
1272− typeComparison localizer expectedElement actualElement
1273− (
1274− "The left side of (::) is an element of type:"
1275− ,
1276− "But the right side is a list filled with elements of type:"
1277− ,
1278− case expectedElement of
1115+ ( D.reflow "I am having trouble with this (::) operator:"
1116+ , typeComparison localizer expectedElement actualElement
1117+ (singular "The left side of (::) is")
1118+ (plural "But you are trying to put that into a list filled with")
1119+ ( case expectedElement of
12791120 T.Type home name [_] | T.isList home name ->
12801121 [ D.toSimpleHint
12811122 "Are you trying to append two lists? The (++) operator\
@@ -1295,16 +1136,11 @@ badConsRight localizer category tipe expected =
12951136
12961137 _ ->
12971138 EmphRight
1298− (
1299− D.reflow "The (::) operator can only add elements onto lists."
1300− ,
1301− loneType localizer tipe expected
1302− (
1303− D.reflow $ toDescription category "The right side is"
1304− ,
1305− [D.fillSep ["But","(::)","needs","a",D.dullyellow "List","on","the","right."]
1306− ]
1307− )
1139+ ( D.reflow "The (::) operator can only add elements onto lists."
1140+ , loneType localizer tipe expected
1141+ (addCategory "The right side is" category)
1142+ [D.fillSep ["But","(::)","needs","a",D.dullyellow "List","on","the","right."]
1143+ ]
13081144 )
13091145
13101146
@@ -1337,13 +1173,11 @@ badAppendLeft :: L.Localizer -> Category -> T.Type -> T.Type -> (D.Doc, D.Doc)
13371173badAppendLeft localizer category tipe expected =
13381174 case toAppendType tipe of
13391175 ANumber thing stringFromThing ->
1340− (
1341− D.fillSep
1176+ ( D.fillSep
13421177 ["The","(++)","operator","can","append","List","and","String"
13431178 ,"values,","but","not",D.dullyellow thing,"values","like","this:"
13441179 ]
1345− ,
1346− D.fillSep
1180+ , D.fillSep
13471181 ["Try","using",D.green stringFromThing,"to","turn","it","into","a","string?"
13481182 ,"Or","put","it","in","[]","to","make","it","a","list?"
13491183 ,"Or","switch","to","the","(::)","operator?"
@@ -1351,20 +1185,16 @@ badAppendLeft localizer category tipe expected =
13511185 )
13521186
13531187 _ ->
1354− (
1355− D.reflow $
1188+ ( D.reflow $
13561189 "The (++) operator cannot append this type of value:"
1357− ,
1358− loneType localizer tipe expected
1359− ( D.reflow $ toDescription category "I am seeing"
1360− ,
1361− [ D.fillSep
1362− ["But","the","(++)","operator","is","only","for","appending"
1363− ,D.dullyellow "List","and",D.dullyellow "String","values."
1364− ,"Maybe","put","this","value","in","[]","to","make","it","a","list?"
1365− ]
1366− ]
1367− )
1190+ , loneType localizer tipe expected
1191+ (addCategory "I am seeing" category)
1192+ [ D.fillSep
1193+ ["But","the","(++)","operator","is","only","for","appending"
1194+ ,D.dullyellow "List","and",D.dullyellow "String","values."
1195+ ,"Maybe","put","this","value","in","[]","to","make","it","a","list?"
1196+ ]
1197+ ]
13681198 )
13691199
13701200
@@ -1373,36 +1203,28 @@ badAppendRight localizer category tipe expected =
13731203 case (toAppendType expected, toAppendType tipe) of
13741204 (AString, ANumber thing stringFromThing) ->
13751205 EmphRight
1376− (
1377− D.fillSep
1206+ ( D.fillSep
13781207 ["I","thought","I","was","appending",D.dullyellow "String","values","here,"
13791208 ,"not",D.dullyellow thing,"values","like","this:"
13801209 ]
1381− ,
1382− D.fillSep
1383− ["Try","using",D.green stringFromThing
1384− ,"to","turn","it","into","a","string?"
1385− ]
1210+ , D.fillSep
1211+ ["Try","using",D.green stringFromThing,"to","turn","it","into","a","string?"]
13861212 )
13871213
13881214 (AList, ANumber thing _) ->
13891215 EmphRight
1390− (
1391− D.fillSep
1216+ ( D.fillSep
13921217 ["I","thought","I","was","appending",D.dullyellow "List","values","here,"
13931218 ,"not",D.dullyellow thing,"values","like","this:"
13941219 ]
1395− ,
1396− D.reflow "Try putting it in [] to make it a list?"
1220+ , D.reflow "Try putting it in [] to make it a list?"
13971221 )
13981222
13991223 (AString, AList) ->
14001224 EmphBoth
1401− (
1402− D.reflow $
1225+ ( D.reflow $
14031226 "The (++) operator needs the same type of value on both sides:"
1404− ,
1405− D.fillSep
1227+ , D.fillSep
14061228 ["I","see","a",D.dullyellow "String","on","the","left","and","a"
14071229 ,D.dullyellow "List","on","the","right.","Which","should","it","be?"
14081230 ,"Does","the","string","need","[]","around","it","to","become","a","list?"
@@ -1411,11 +1233,9 @@ badAppendRight localizer category tipe expected =
14111233
14121234 (AList, AString) ->
14131235 EmphBoth
1414− (
1415− D.reflow $
1236+ ( D.reflow $
14161237 "The (++) operator needs the same type of value on both sides:"
1417− ,
1418− D.fillSep
1238+ , D.fillSep
14191239 ["I","see","a",D.dullyellow "List","on","the","left","and","a"
14201240 ,D.dullyellow "String","on","the","right.","Which","should","it","be?"
14211241 ,"Does","the","string","need","[]","around","it","to","become","a","list?"
@@ -1424,19 +1244,12 @@ badAppendRight localizer category tipe expected =
14241244
14251245 (_,_) ->
14261246 EmphBoth
1427− (
1428− D.reflow $
1247+ ( D.reflow $
14291248 "The (++) operator cannot append these two values:"
1430− ,
1431− typeComparison localizer expected tipe
1432− (
1433− "I already figured out that the left side of (++) is:"
1434− ,
1435− toDescription category $
1436− "But this clashes with the right side, which is"
1437− ,
1438− []
1439− )
1249+ , typeComparison localizer expected tipe
1250+ (singular "I already figured out that the left side of (++) is")
1251+ (addCategory "But this clashes with the right side, which is" category)
1252+ []
14401253 )
14411254
14421255
@@ -1450,11 +1263,9 @@ data ThisThenThat = FloatInt | IntFloat
14501263badCast :: N.Name -> ThisThenThat -> RightDocs
14511264badCast op thisThenThat =
14521265 EmphBoth
1453− (
1454− D.reflow $
1266+ ( D.reflow $
14551267 "I need both sides of (" <> N.toString op <> ") to be the exact same type. Both Int or both Float."
1456− ,
1457− let
1268+ , let
14581269 anInt = ["an", D.dullyellow "Int"]
14591270 aFloat = ["a", D.dullyellow "Float"]
14601271 toFloat = D.green "toFloat"
@@ -1508,18 +1319,14 @@ badListAdd localizer category direction tipe expected =
15081319 "I cannot do addition with lists:"
15091320 ,
15101321 loneType localizer tipe expected
1511− (
1512− D.reflow $ toDescription category $
1513− "The " <> direction <> " side of (+) is"
1514− ,
1515− [ D.fillSep
1516− ["But","(+)","only","works","with",D.dullyellow "Int","and",D.dullyellow "Float","values."
1517− ]
1518− , D.toFancyHint
1519− ["Switch","to","the",D.green "(++)","operator","to","append","lists!"
1520− ]
1521− ]
1522− )
1322+ (addCategory ("The " <> direction <> " side of (+) is") category)
1323+ [ D.fillSep
1324+ ["But","(+)","only","works","with",D.dullyellow "Int","and",D.dullyellow "Float","values."
1325+ ]
1326+ , D.toFancyHint
1327+ ["Switch","to","the",D.green "(++)","operator","to","append","lists!"
1328+ ]
1329+ ]
15231330 )
15241331
15251332
@@ -1542,10 +1349,8 @@ badMath localizer category operation direction op tipe expected otherHints =
15421349 operation ++ " does not work with this value:"
15431350 ,
15441351 loneType localizer tipe expected
1545− ( D.reflow $ toDescription category $
1546− "The " <> direction <> " side of (" <> op <> ") is"
1547− ,
1548− [ D.fillSep
1352+ (addCategory ("The " <> direction <> " side of (" <> op <> ") is") category)
1353+ ( [ D.fillSep
15491354 ["But","(" <> D.fromString op <> ")","only","works","with"
15501355 ,D.dullyellow "Int","and",D.dullyellow "Float","values."
15511356 ]
@@ -1578,14 +1383,13 @@ badFDiv localizer direction tipe expected =
15781383
15791384 else
15801385 loneType localizer tipe expected
1581− (
1582− D.fillSep
1583− ["The",direction,"side","of","(/)","must","be","a"
1584− ,D.dullyellow "Float" <> ","
1585− ,"but","instead","I","am","seeing:"
1586− ]
1587− , []
1386+ (\_ ->
1387+ D.fillSep
1388+ ["The",direction,"side","of","(/)","must","be","a"
1389+ ,D.dullyellow "Float" <> ",","but","instead","I","am","seeing:"
1390+ ]
15881391 )
1392+ []
15891393 )
15901394
15911395
@@ -1614,14 +1418,13 @@ badIDiv localizer direction tipe expected =
16141418 ]
16151419 else
16161420 loneType localizer tipe expected
1617− (
1618− D.fillSep
1619− ["The",direction,"side","of","(//)","must","be","an"
1620− ,D.dullyellow "Int" <> ","
1621− ,"but","instead","I","am","seeing:"
1622− ]
1623− , []
1421+ ( \_ ->
1422+ D.fillSep
1423+ ["The",direction,"side","of","(//)","must","be","an"
1424+ ,D.dullyellow "Int" <> ",","but","instead","I","am","seeing:"
1425+ ]
16241426 )
1427+ []
16251428 )
16261429
16271430
@@ -1636,14 +1439,13 @@ badBool localizer op direction tipe expected =
16361439 "I am struggling with this boolean operation:"
16371440 ,
16381441 loneType localizer tipe expected
1639− (
1640− D.fillSep
1641− ["Both","sides","of","(" <> op <> ")","must","be"
1642− ,D.dullyellow "Bool","values,","but","the",direction,"side","is:"
1643− ]
1644− ,
1645− []
1442+ ( \_ ->
1443+ D.fillSep
1444+ ["Both","sides","of","(" <> op <> ")","must","be"
1445+ ,D.dullyellow "Bool","values,","but","the",direction,"side","is:"
1446+ ]
16461447 )
1448+ []
16471449 )
16481450
16491451
@@ -1658,23 +1460,19 @@ badCompLeft localizer category op direction tipe expected =
16581460 "I cannot do a comparison with this value:"
16591461 ,
16601462 loneType localizer tipe expected
1661− (
1662− D.reflow $ toDescription category $
1663− "The " <> direction <> " side of (" <> op <> ") is"
1664− ,
1665− [ D.fillSep
1666− ["But","(" <> D.fromString op <> ")","only","works","on"
1667− ,D.dullyellow "Int" <> ","
1668− ,D.dullyellow "Float" <> ","
1669− ,D.dullyellow "Char" <> ","
1670− ,"and"
1671− ,D.dullyellow "String"
1672− ,"values.","It","can","work","on","lists","and","tuples"
1673− ,"of","comparable","values","as","well,","but","it","is"
1674− ,"usually","better","to","find","a","different","path."
1675− ]
1676− ]
1677− )
1463+ (addCategory ("The " <> direction <> " side of (" <> op <> ") is") category)
1464+ [ D.fillSep
1465+ ["But","(" <> D.fromString op <> ")","only","works","on"
1466+ ,D.dullyellow "Int" <> ","
1467+ ,D.dullyellow "Float" <> ","
1468+ ,D.dullyellow "Char" <> ","
1469+ ,"and"
1470+ ,D.dullyellow "String"
1471+ ,"values.","It","can","work","on","lists","and","tuples"
1472+ ,"of","comparable","values","as","well,","but","it","is"
1473+ ,"usually","better","to","find","a","different","path."
1474+ ]
1475+ ]
16781476 )
16791477
16801478
@@ -1686,15 +1484,11 @@ badCompRight localizer op tipe expected =
16861484 "I need both sides of (" <> op <> ") to be the same type:"
16871485 ,
16881486 typeComparison localizer expected tipe
1689− (
1690− "The left side of is:"
1691− ,
1692− "But the right side is:"
1693− ,
1694− [ D.reflow $
1695− "I cannot compare different types though! Which side of (" <> op <> ") is the problem?"
1696− ]
1697− )
1487+ (singular "The left side of is")
1488+ (singular "But the right side is")
1489+ [ D.reflow $
1490+ "I cannot compare different types though! Which side of (" <> op <> ") is the problem?"
1491+ ]
16981492 )
16991493
17001494
@@ -1710,21 +1504,15 @@ badEquality localizer op tipe expected =
17101504 "I need both sides of (" <> op <> ") to be the same type:"
17111505 ,
17121506 typeComparison localizer expected tipe
1713− (
1714− "The left side of is:"
1715− ,
1716− "But the right side is:"
1717− ,
1718− if isFloat tipe || isFloat expected then
1719− [ D.toSimpleNote $
1720− "Equality on floats is not 100% reliable due to the design of IEEE 754. I\
1721− \ recommend a check like (abs (x - y) < 0.0001) instead."
1722− ]
1507+ (singular "The left side of is")
1508+ (singular "But the right side is")
1509+ [ if isFloat tipe || isFloat expected then
1510+ D.toSimpleNote $
1511+ "Equality on floats is not 100% reliable due to the design of IEEE 754. I\
1512+ \ recommend a check like (abs (x - y) < 0.0001) instead."
17231513 else
1724− [ D.reflow $
1725− "Different types can never be equal though! Which side is messed up?"
1726− ]
1727− )
1514+ D.reflow "Different types can never be equal though! Which side is messed up?"
1515+ ]
17281516 )
17291517
17301518