@@ -121,15 +121,31 @@ _add('2', '2');
121
121
122
122
``` javascript
123
123
add (' 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’.
125
133
```
126
134
127
135
Type checking is performed as arguments are provided (rather than once all
128
136
arguments have been provided), so type errors are reported early:
129
137
130
138
``` javascript
131
139
add (' 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’.
133
149
```
134
150
135
151
### Types
@@ -450,7 +466,17 @@ cmp('z', 'a');
450
466
// => 1
451
467
452
468
cmp (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.
454
480
```
455
481
456
482
#### ` NullaryType `
@@ -496,10 +522,26 @@ rem(42, 5);
496
522
// => 2
497
523
498
524
rem (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’.
500
534
501
535
rem (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’.
503
545
```
504
546
505
547
#### ` UnaryType `
@@ -516,7 +558,15 @@ sum([1, 2, 3, 4]);
516
558
// => 10
517
559
518
560
sum ([' 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’.
520
570
```
521
571
522
572
To define a unary type ` t a ` one must provide:
@@ -574,7 +624,17 @@ fromMaybe(0, Nothing);
574
624
// => 0
575
625
576
626
fromMaybe (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.
578
638
```
579
639
580
640
#### ` BinaryType `
@@ -648,7 +708,15 @@ showCard(Pair('A', '♠'));
648
708
// => 'A♠'
649
709
650
710
showCard (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’.
652
720
```
653
721
654
722
#### ` EnumType `
@@ -669,11 +737,6 @@ For example:
669
737
// TimeUnit :: Type
670
738
const TimeUnit = $ .EnumType ([' milliseconds' , ' seconds' , ' minutes' , ' hours' ]);
671
739
672
- // env :: [Type]
673
- const env = $ .env .concat ([TimeUnit, $ .ValidDate , $ .ValidNumber ]);
674
-
675
- const def = $ .create (true , env);
676
-
677
740
// convertTo :: TimeUnit -> ValidDate -> ValidNumber
678
741
const convertTo =
679
742
def (' convertTo' ,
@@ -692,7 +755,15 @@ convertTo('seconds', new Date(1000));
692
755
// => 1
693
756
694
757
convertTo (' 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")’.
696
767
```
697
768
698
769
#### ` RecordType `
@@ -711,18 +782,12 @@ RecordType :: {Type} -> Type
711
782
For example:
712
783
713
784
``` 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
-
720
785
// Point :: Type
721
- const Point = $ .RecordType ({x: FiniteNumber, y: FiniteNumber});
786
+ const Point = $ .RecordType ({x: $ . FiniteNumber , y: $ . FiniteNumber });
722
787
723
788
// dist :: Point -> Point -> FiniteNumber
724
789
const dist =
725
- def (' dist' , {}, [Point , Point , FiniteNumber],
790
+ def (' dist' , {}, [Point , Point , $ . FiniteNumber ],
726
791
(p , q ) => Math .sqrt (Math .pow (p .x - q .x , 2 ) + Math .pow (p .y - q .y , 2 )));
727
792
728
793
dist ({x: 0 , y: 0 }, {x: 3 , y: 4 });
@@ -732,10 +797,26 @@ dist({x: 0, y: 0}, {x: 3, y: 4, color: 'red'});
732
797
// => 5
733
798
734
799
dist ({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 }’.
736
809
737
810
dist (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 }’.
739
820
```
740
821
741
822
### Type classes
@@ -758,7 +839,17 @@ _concat([1, 2], [3, 4]);
758
839
// => [1, 2, 3, 4]
759
840
760
841
_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.
762
853
```
763
854
764
855
The type of ` _concat ` is misleading: it suggests that it can operate on any
@@ -793,10 +884,26 @@ concat([1, 2], [3, 4]);
793
884
// => [1, 2, 3, 4]
794
885
795
886
concat ({}, {});
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.
797
896
798
897
concat (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.
800
907
```
801
908
802
909
Multiple constraints may be placed on a type variable by including multiple
0 commit comments