@@ -23,7 +23,7 @@ const Integer = ...;
23
23
// NonZeroInteger :: Type
24
24
const NonZeroInteger = ... ;
25
25
26
- // env :: [ Type]
26
+ // env :: Array Type
27
27
const env = $ .env .concat ([Integer, NonZeroInteger]);
28
28
```
29
29
@@ -165,6 +165,14 @@ $.Any :: Type
165
165
166
166
Type comprising every JavaScript value.
167
167
168
+ #### ` AnyFunction `
169
+
170
+ ``` haskell
171
+ $. AnyFunction :: Type
172
+ ```
173
+
174
+ Type comprising every Function value.
175
+
168
176
#### ` Arguments `
169
177
170
178
``` haskell
@@ -218,10 +226,15 @@ Type comprising every [`ValidNumber`](#validnumber) value except `Infinity` and
218
226
#### ` Function `
219
227
220
228
``` haskell
221
- $. Function :: Type
229
+ $. Function :: [ Type ] -> Type
222
230
```
223
231
224
- Type comprising every Function value.
232
+ Constructor for Function types.
233
+
234
+ Examples:
235
+
236
+ - ` $.Function([$.Date, $.String]) ` represents the ` Date -> String ` type; and
237
+ - ` $.Function([a, b, a]) ` represents the ` (a, b) -> a ` type.
225
238
226
239
#### ` Integer `
227
240
@@ -474,63 +487,6 @@ bodies of incoming POST requests against these types.
474
487
475
488
sanctuary-def provides several functions for defining types.
476
489
477
- #### ` TypeVariable `
478
-
479
- Polymorphism is powerful. Not being able to define a function for all types
480
- would be very limiting indeed: one couldn't even define the identity function!
481
-
482
- ``` haskell
483
- TypeVariable :: String -> Type
484
- ```
485
-
486
- Before defining a polymorphic function one must define one or more type
487
- variables:
488
-
489
- ``` javascript
490
- const a = $ .TypeVariable (' a' );
491
- const b = $ .TypeVariable (' b' );
492
-
493
- // id :: a -> a
494
- const id = def (' id' , {}, [a, a], x => x);
495
-
496
- id (42 );
497
- // => 42
498
-
499
- id (null );
500
- // => null
501
- ```
502
-
503
- The same type variable may be used in multiple positions, creating a
504
- constraint:
505
-
506
- ``` javascript
507
- // cmp :: a -> a -> Number
508
- const cmp =
509
- def (' cmp' , {}, [a, a, $ .Number ], (x , y ) => x < y ? - 1 : x > y ? 1 : 0 );
510
-
511
- cmp (42 , 42 );
512
- // => 0
513
-
514
- cmp (' a' , ' z' );
515
- // => -1
516
-
517
- cmp (' z' , ' a' );
518
- // => 1
519
-
520
- cmp (0 , ' 1' );
521
- // ! TypeError: Type-variable constraint violation
522
- //
523
- // cmp :: a -> a -> Number
524
- // ^ ^
525
- // 1 2
526
- //
527
- // 1) 0 :: Number
528
- //
529
- // 2) "1" :: String
530
- //
531
- // Since there is no type of which all the above values are members, the type-variable constraint has been violated.
532
- ```
533
-
534
490
#### ` NullaryType `
535
491
536
492
` NullaryType ` is used to construct types with no type variables. ` $.Number ` is
@@ -602,7 +558,7 @@ rem(42, 0);
602
558
defined via ` UnaryType ` .
603
559
604
560
``` javascript
605
- // sum :: [ Number] -> Number
561
+ // sum :: Array Number -> Number
606
562
const sum =
607
563
def (' sum' , {}, [$ .Array ($ .Number ), $ .Number ], xs => xs .reduce ((x , y ) => x + y, 0 ));
608
564
@@ -629,9 +585,10 @@ To define a unary type `t a` one must provide:
629
585
if (and only if) the value is a member of ` t x ` for some type ` x ` ;
630
586
631
587
- a function which takes any value of type ` t a ` and returns an array
632
- of the values of type ` a ` contained in the ` t ` (exposed as ` t._1 ` ); and
588
+ of the values of type ` a ` contained in the ` t ` (exposed as
589
+ ` t.types.$1.extractor ` ); and
633
590
634
- - the type of ` a ` (exposed as ` t.$1 ` ).
591
+ - the type of ` a ` (exposed as ` t.types.$1.type ` ).
635
592
636
593
``` haskell
637
594
UnaryType :: String -> (Any -> Boolean ) -> (t a -> [a ]) -> Type -> Type
@@ -701,14 +658,16 @@ To define a binary type `t a b` one must provide:
701
658
` x ` and ` y ` ;
702
659
703
660
- a function which takes any value of type ` t a b ` and returns an array
704
- of the values of type ` a ` contained in the ` t ` (exposed as ` t._1 ` );
661
+ of the values of type ` a ` contained in the ` t ` (exposed as
662
+ ` t.types.$1.extractor ` );
705
663
706
664
- a function which takes any value of type ` t a b ` and returns an array
707
- of the values of type ` b ` contained in the ` t ` (exposed as ` t._2 ` );
665
+ of the values of type ` b ` contained in the ` t ` (exposed as
666
+ ` t.types.$2.extractor ` );
708
667
709
- - the type of ` a ` (exposed as ` t.$1 ` ); and
668
+ - the type of ` a ` (exposed as ` t.types.$1.type ` ); and
710
669
711
- - the type of ` b ` (exposed as ` t.$2 ` ).
670
+ - the type of ` b ` (exposed as ` t.types.$2.type ` ).
712
671
713
672
``` haskell
714
673
BinaryType :: String -> (Any -> Boolean ) -> (t a b -> [a ]) -> (t a b -> [b ]) -> Type -> Type -> Type
@@ -870,6 +829,115 @@ dist(0);
870
829
// The value at position 1 is not a member of ‘{ x :: FiniteNumber, y :: FiniteNumber }’.
871
830
```
872
831
832
+ #### ` TypeVariable `
833
+
834
+ Polymorphism is powerful. Not being able to define a function for all types
835
+ would be very limiting indeed: one couldn't even define the identity function!
836
+
837
+ ``` haskell
838
+ TypeVariable :: String -> Type
839
+ ```
840
+
841
+ Before defining a polymorphic function one must define one or more type
842
+ variables:
843
+
844
+ ``` javascript
845
+ const a = $ .TypeVariable (' a' );
846
+ const b = $ .TypeVariable (' b' );
847
+
848
+ // id :: a -> a
849
+ const id = def (' id' , {}, [a, a], x => x);
850
+
851
+ id (42 );
852
+ // => 42
853
+
854
+ id (null );
855
+ // => null
856
+ ```
857
+
858
+ The same type variable may be used in multiple positions, creating a
859
+ constraint:
860
+
861
+ ``` javascript
862
+ // cmp :: a -> a -> Number
863
+ const cmp =
864
+ def (' cmp' , {}, [a, a, $ .Number ], (x , y ) => x < y ? - 1 : x > y ? 1 : 0 );
865
+
866
+ cmp (42 , 42 );
867
+ // => 0
868
+
869
+ cmp (' a' , ' z' );
870
+ // => -1
871
+
872
+ cmp (' z' , ' a' );
873
+ // => 1
874
+
875
+ cmp (0 , ' 1' );
876
+ // ! TypeError: Type-variable constraint violation
877
+ //
878
+ // cmp :: a -> a -> Number
879
+ // ^ ^
880
+ // 1 2
881
+ //
882
+ // 1) 0 :: Number
883
+ //
884
+ // 2) "1" :: String
885
+ //
886
+ // Since there is no type of which all the above values are members, the type-variable constraint has been violated.
887
+ ```
888
+
889
+ #### ` UnaryTypeVariable `
890
+
891
+ As its name suggests, ` UnaryTypeVariable ` combines [ ` UnaryType ` ] ( #unarytype )
892
+ and [ ` TypeVariable ` ] ( #typevariable ) .
893
+
894
+ To define a unary type variable ` t a ` one must provide:
895
+
896
+ - a name (conventionally matching ` ^[a-z]$ ` ); and
897
+
898
+ - the type of ` a ` (exposed as ` t.types.$1.type ` ).
899
+
900
+ ``` haskell
901
+ UnaryTypeVariable :: String -> Type -> Type
902
+ ```
903
+
904
+ Consider the type of a generalized ` map ` :
905
+
906
+ ``` haskell
907
+ map :: Functor f => (a -> b ) -> f a -> f b
908
+ ```
909
+
910
+ `f` is a unary type variable. With two (regular) type variables, one unary
911
+ type variable , and one [type class ](# type - classes ) it's possible to define
912
+ a fully polymorphic `map` function:
913
+
914
+ ```javascript
915
+ const a = $. TypeVariable (' a' );
916
+ const b = $. TypeVariable (' b' );
917
+ const f = $. UnaryTypeVariable (' f' );
918
+
919
+ // Functor :: TypeClass
920
+ const Functor = ... ;
921
+
922
+ // map :: Functor f => (a -> b ) -> f a -> f b
923
+ const map =
924
+ def('map',
925
+ {f: [Functor ]},
926
+ [$. Function ([a, b]), f(a), f(b)],
927
+ (fn, functor) => functor. map (fn));
928
+ ```
929
+
930
+ Whereas a regular type variable is fully resolved (` a ` might become
931
+ ` Array (Array String) ` , for example), a unary type variable defers to
932
+ its type argument, which may itself be a type variable. The type argument
933
+ corresponds to the type argument of a unary type or the * second* type
934
+ argument of a binary type. The second type argument of ` Map k v ` , for
935
+ example, is ` v ` . One could replace ` Functor => f ` with ` Map k ` or with
936
+ ` Map Integer ` , but not with ` Map ` .
937
+
938
+ This shallow inspection makes it possible to constrain a value's "outer"
939
+ and "inner" types independently.
940
+
873
941
### Type classes
874
942
875
943
` concatS ` , defined earlier, is a function which concatenates two strings.
0 commit comments