@@ -121,15 +121,31 @@ _add('2', '2');
121121
122122``` javascript
123123add (' 2' , ' 2' );
124- // ! TypeError: ‘add’ expected a value of type Number as its first argument; received "2"
124+ // ! TypeError: Invalid value
125+ //
126+ // add :: Number -> Number -> Number
127+ // ^^^^^^
128+ // 1
129+ //
130+ // 1) "2" :: String
131+ //
132+ // The value at position 1 is not a member of ‘Number’.
125133```
126134
127135Type checking is performed as arguments are provided (rather than once all
128136arguments have been provided), so type errors are reported early:
129137
130138``` javascript
131139add (' X' );
132- // ! TypeError: ‘add’ expected a value of type Number as its first argument; received "X"
140+ // ! TypeError: Invalid value
141+ //
142+ // add :: Number -> Number -> Number
143+ // ^^^^^^
144+ // 1
145+ //
146+ // 1) "X" :: String
147+ //
148+ // The value at position 1 is not a member of ‘Number’.
133149```
134150
135151### Types
@@ -450,7 +466,17 @@ cmp('z', 'a');
450466// => 1
451467
452468cmp (0 , ' 1' );
453- // ! TypeError: ‘cmp’ expected a value of type Number as its second argument; received "1"
469+ // ! TypeError: Type-variable constraint violation
470+ //
471+ // cmp :: a -> a -> Number
472+ // ^ ^
473+ // 1 2
474+ //
475+ // 1) 0 :: Number
476+ //
477+ // 2) "1" :: String
478+ //
479+ // Since there is no type of which all the above values are members, the type-variable constraint has been violated.
454480```
455481
456482#### ` NullaryType `
@@ -496,10 +522,26 @@ rem(42, 5);
496522// => 2
497523
498524rem (0.5 );
499- // ! TypeError: ‘rem’ expected a value of type Integer as its first argument; received 0.5
525+ // ! TypeError: Invalid value
526+ //
527+ // rem :: Integer -> NonZeroInteger -> Integer
528+ // ^^^^^^^
529+ // 1
530+ //
531+ // 1) 0.5 :: Number
532+ //
533+ // The value at position 1 is not a member of ‘Integer’.
500534
501535rem (42 , 0 );
502- // ! TypeError: ‘rem’ expected a value of type NonZeroInteger as its second argument; received 0
536+ // ! TypeError: Invalid value
537+ //
538+ // rem :: Integer -> NonZeroInteger -> Integer
539+ // ^^^^^^^^^^^^^^
540+ // 1
541+ //
542+ // 1) 0 :: Number
543+ //
544+ // The value at position 1 is not a member of ‘NonZeroInteger’.
503545```
504546
505547#### ` UnaryType `
@@ -516,7 +558,15 @@ sum([1, 2, 3, 4]);
516558// => 10
517559
518560sum ([' 1' , ' 2' , ' 3' , ' 4' ]);
519- // ! TypeError: ‘sum’ expected a value of type (Array Number) as its first argument; received ["1", "2", "3", "4"]
561+ // ! TypeError: Invalid value
562+ //
563+ // sum :: Array Number -> Number
564+ // ^^^^^^
565+ // 1
566+ //
567+ // 1) "1" :: String
568+ //
569+ // The value at position 1 is not a member of ‘Number’.
520570```
521571
522572To define a unary type ` t a ` one must provide:
@@ -574,7 +624,17 @@ fromMaybe(0, Nothing);
574624// => 0
575625
576626fromMaybe (0 , Just (' XXX' ));
577- // ! TypeError: ‘fromMaybe’ expected a value of type (Maybe Number) as its second argument; received Just("XXX")
627+ // ! TypeError: Type-variable constraint violation
628+ //
629+ // fromMaybe :: a -> Maybe a -> a
630+ // ^ ^
631+ // 1 2
632+ //
633+ // 1) 0 :: Number
634+ //
635+ // 2) "XXX" :: String
636+ //
637+ // Since there is no type of which all the above values are members, the type-variable constraint has been violated.
578638```
579639
580640#### ` BinaryType `
@@ -648,7 +708,15 @@ showCard(Pair('A', '♠'));
648708// => 'A♠'
649709
650710showCard (Pair (' X' , ' ♠' ));
651- // ! TypeError: ‘showCard’ expected a value of type (Pair Rank Suit) as its first argument; received Pair("X", "♠")
711+ // ! TypeError: Invalid value
712+ //
713+ // showCard :: Pair Rank Suit -> String
714+ // ^^^^
715+ // 1
716+ //
717+ // 1) "X" :: String
718+ //
719+ // The value at position 1 is not a member of ‘Rank’.
652720```
653721
654722#### ` EnumType `
@@ -669,11 +737,6 @@ For example:
669737// TimeUnit :: Type
670738const TimeUnit = $ .EnumType ([' milliseconds' , ' seconds' , ' minutes' , ' hours' ]);
671739
672- // env :: [Type]
673- const env = $ .env .concat ([TimeUnit, $ .ValidDate , $ .ValidNumber ]);
674-
675- const def = $ .create (true , env);
676-
677740// convertTo :: TimeUnit -> ValidDate -> ValidNumber
678741const convertTo =
679742def (' convertTo' ,
@@ -692,7 +755,15 @@ convertTo('seconds', new Date(1000));
692755// => 1
693756
694757convertTo (' days' , new Date (1000 ));
695- // ! TypeError: ‘convertTo’ expected a value of type ("milliseconds" | "seconds" | "minutes" | "hours") as its first argument; received "days"
758+ // ! TypeError: Invalid value
759+ //
760+ // convertTo :: ("milliseconds" | "seconds" | "minutes" | "hours") -> ValidDate -> ValidNumber
761+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
762+ // 1
763+ //
764+ // 1) "days" :: String
765+ //
766+ // The value at position 1 is not a member of ‘("milliseconds" | "seconds" | "minutes" | "hours")’.
696767```
697768
698769#### ` RecordType `
@@ -711,18 +782,12 @@ RecordType :: {Type} -> Type
711782For example:
712783
713784``` javascript
714- // FiniteNumber :: Type
715- const FiniteNumber = $ .NullaryType (
716- ' my-package/FiniteNumber' ,
717- x => Object .prototype .toString .call (x) === ' [object Number]' && isFinite (x)
718- );
719-
720785// Point :: Type
721- const Point = $ .RecordType ({x: FiniteNumber, y: FiniteNumber});
786+ const Point = $ .RecordType ({x: $ . FiniteNumber , y: $ . FiniteNumber });
722787
723788// dist :: Point -> Point -> FiniteNumber
724789const dist =
725- def (' dist' , {}, [Point , Point , FiniteNumber],
790+ def (' dist' , {}, [Point , Point , $ . FiniteNumber ],
726791 (p , q ) => Math .sqrt (Math .pow (p .x - q .x , 2 ) + Math .pow (p .y - q .y , 2 )));
727792
728793dist ({x: 0 , y: 0 }, {x: 3 , y: 4 });
@@ -732,10 +797,26 @@ dist({x: 0, y: 0}, {x: 3, y: 4, color: 'red'});
732797// => 5
733798
734799dist ({x: 0 , y: 0 }, {x: NaN , y: NaN });
735- // ! TypeError: ‘dist’ expected a value of type { x :: FiniteNumber, y :: FiniteNumber } as its second argument; received {"x": NaN, "y": NaN}
800+ // ! TypeError: Invalid value
801+ //
802+ // dist :: { x :: FiniteNumber, y :: FiniteNumber } -> { x :: FiniteNumber, y :: FiniteNumber } -> FiniteNumber
803+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
804+ // 1
805+ //
806+ // 1) {"x": NaN, "y": NaN} :: Object, StrMap Number
807+ //
808+ // The value at position 1 is not a member of ‘{ x :: FiniteNumber, y :: FiniteNumber }’.
736809
737810dist (0 );
738- // ! TypeError: ‘dist’ expected a value of type { x :: FiniteNumber, y :: FiniteNumber } as its first argument; received 0
811+ // ! TypeError: Invalid value
812+ //
813+ // dist :: { x :: FiniteNumber, y :: FiniteNumber } -> { x :: FiniteNumber, y :: FiniteNumber } -> FiniteNumber
814+ // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
815+ // 1
816+ //
817+ // 1) 0 :: Number
818+ //
819+ // The value at position 1 is not a member of ‘{ x :: FiniteNumber, y :: FiniteNumber }’.
739820```
740821
741822### Type classes
@@ -758,7 +839,17 @@ _concat([1, 2], [3, 4]);
758839// => [1, 2, 3, 4]
759840
760841_concat ([1 , 2 ], ' buzz' );
761- // ! TypeError: ‘_concat’ expected a value of type (Array Number) as its second argument; received "buzz"
842+ // ! TypeError: Type-variable constraint violation
843+ //
844+ // _concat :: a -> a -> a
845+ // ^ ^
846+ // 1 2
847+ //
848+ // 1) [1, 2] :: Array Number
849+ //
850+ // 2) "buzz" :: String
851+ //
852+ // Since there is no type of which all the above values are members, the type-variable constraint has been violated.
762853```
763854
764855The type of ` _concat ` is misleading: it suggests that it can operate on any
@@ -793,10 +884,26 @@ concat([1, 2], [3, 4]);
793884// => [1, 2, 3, 4]
794885
795886concat ({}, {});
796- // ! TypeError: ‘concat’ requires ‘a’ to implement Semigroup; Object does not
887+ // ! TypeError: Type-class constraint violation
888+ //
889+ // concat :: Semigroup a => a -> a -> a
890+ // ^^^^^^^^^^^ ^
891+ // 1
892+ //
893+ // 1) {} :: Object, StrMap ???
894+ //
895+ // ‘concat’ requires ‘a’ to satisfy the Semigroup type-class constraint; the value at position 1 does not.
797896
798897concat (null , null );
799- // ! TypeError: ‘concat’ requires ‘a’ to implement Semigroup; Null does not
898+ // ! TypeError: Type-class constraint violation
899+ //
900+ // concat :: Semigroup a => a -> a -> a
901+ // ^^^^^^^^^^^ ^
902+ // 1
903+ //
904+ // 1) null :: Null
905+ //
906+ // ‘concat’ requires ‘a’ to satisfy the Semigroup type-class constraint; the value at position 1 does not.
800907```
801908
802909Multiple constraints may be placed on a type variable by including multiple
0 commit comments