commit aa72ace7f55b0acfb16ec8b509bca226920d475a
parent d87b895cb1f0fcb8cb3e9ab38882a49c77399e1c
Author: Georges Dupéron <georges.duperon@gmail.com>
Date: Thu, 12 Jan 2017 21:18:16 +0100
Split package to avoid dependency on aful for just the lib itself
Diffstat:
13 files changed, 167 insertions(+), 134 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -3,4 +3,4 @@
.\#*
.DS_Store
compiled/
-/doc/
+/*/doc/
diff --git a/.travis.yml b/.travis.yml
@@ -42,7 +42,7 @@ before_install:
- export PATH="${RACKET_DIR}/bin:${PATH}" #install-racket.sh can't set for us
install:
- - raco pkg install -j 1 --deps search-auto
+ - raco pkg install -j 1 --deps search-auto ./typed-map ./typed-map-lib ./typed-map-test
before_script:
@@ -50,8 +50,8 @@ before_script:
# `raco pkg install --deps search-auto` to install any required
# packages without it getting stuck on a confirmation prompt.
script:
- - raco test -p typed-map
- - raco setup --check-pkg-deps --pkgs typed-map
+ - raco test -p typed-map typed-map-lib typed-map-test
+ - raco setup --check-pkg-deps --pkgs typed-map typed-map-lib typed-map-test
- raco pkg install --deps search-auto doc-coverage
- raco doc-coverage typed-map
diff --git a/info.rkt b/info.rkt
@@ -1,17 +0,0 @@
-#lang info
-(define collection "typed-map")
-(define deps '("base"
- "rackunit-lib"
- "typed-racket-lib"
- "typed-racket-more"))
-(define build-deps '("scribble-lib"
- "racket-doc"
- "aful"
- "typed-racket-doc"))
-(define scribblings '(("scribblings/typed-map.scrbl" ())))
-(define pkg-desc
- (string-append "Type inference helper for map with Typed/Racket."
- " Supports afl, un-annotated lambdas and polymorphic"
- " functions."))
-(define version "1.0")
-(define pkg-authors '("Georges Dupéron"))
diff --git a/scribblings/typed-map.scrbl b/scribblings/typed-map.scrbl
@@ -1,112 +0,0 @@
-#lang scribble/manual
-@require[scribble/example
- @for-label[typed-map]]
-
-@title{typed-map}
-@author[@author+email["Georges Dupéron" "georges.duperon@gmail.com"]]
-
-@(module orig racket/base
- (require scribble/manual
- (for-label racket/base))
- (provide orig:map orig:foldl orig:foldr)
- (define orig:map @racket[map])
- (define orig:foldl @racket[foldl])
- (define orig:foldr @racket[foldr]))
-@(require 'orig)
-
-@defmodule[typed-map]
-
-@defproc[#:kind "syntax"
- (map [f (→ A ... B)] [l (Listof A)] ...) (Listof B)]{
- Like @orig:map from @racketmodname[typed/racket/base], but with better type
- inference for Typed Racket.
-
- When @racket[f] is a literal lambda of the form
- @racket[(λ (arg ...) body ...)], it is not necessary to specify the type of
- the arguments, as they will be inferred from the list.
-
- @examples[#:eval ((make-eval-factory '(typed-map) #:lang 'typed/racket))
- (map (λ (x) (* x 2)) '(1 2 3))
- (let ([l '(4 5 6)])
- (map (λ (x) (* x 2)) l))]
-
- This enables the use of @racket[#,(hash-lang) #,(racketmodname afl)] for
- @racket[map] in Typed Racket.
-
- Furthermore, when @racket[f] is a polymorphic function, type annotations are
- not needed:
-
- @examples[#:eval ((make-eval-factory '(typed-map) #:lang 'typed/racket))
- (map car '([a . 1] [b . 2] [c . 3]))]
-
- Compare this with the behaviour of @orig:map from
- @racketmodname[racket/base], which generates a type error:
-
- @examples[#:eval ((make-eval-factory '() #:lang 'typed/racket))
- (eval:alts (#,orig:map car '([a . 1] [b . 2] [c . 3]))
- (eval:error (map car '([a . 1] [b . 2] [c . 3]))))]
-
- When used as an identifier, the @racket[map] macro expands to the original
- @orig:map from @racketmodname[typed/racket/base]:
-
- @examples[#:eval ((make-eval-factory '(typed-map) #:lang 'typed/racket))
- (eval:alts (require (only-in racket/base [#,orig:map orig:map]))
- (require (only-in racket/base [map orig:map])))
- (equal? map orig:map)]
-
- Note that the implementation expands to a large expression, and makes use of
- @racket[set!] internally to build the result list. The trick used proceeds as
- follows:
- @itemlist[
- @item{It uses @racket[(reverse (reverse l))] to generalise the type of the
- list, without having to express that type, so that Type / Racket infers a
- more general type of the form @racket[(Listof A)], without detecting that the
- output is identical to the input. An unoptimizable guard prevents the
- double-reverse from actually being executed, so it does not incur a
- performance cost.}
- @item{It uses a
- @seclink["Named_let" #:doc '(lib "scribblings/guide/guide.scrbl")]{named
- @racket[let]} to perform the loop. The function @racket[f] is never passed
- as an argument to another polymorphic function, and is instead directly
- called with the appropriate arguments. The error message ``Polymorphic
- function `map' could not be applied to arguments'' is therefore not raised.}
- @item{To have the most precise and correct types, it uses a named let with a
- single variable containing the list (with the generalized type). An outer let
- binds a mutable accumulator, initialized with a single-element list
- containing the result of applying @racket[f] on the first element of the
- list. Since all elements of the list belong to the generalized type, the
- result of calling @racket[f] on any element has the same type, therefore the
- accumulator has the type @racket[(Listof B)], where @racket[B] is the
- inferred type of the result of @racket[f].}]}
-
-
-@defproc[#:kind "syntax"
- (foldl [f (→ A ... Acc Acc)] [init Acc] [l (Listof A)] ...) Acc]{
- Like @orig:foldl from @racketmodname[typed/racket/base] but with better type
- inference for Typed Racket.
-
- This form is implemented in the same way as the overloaded version of
- @racket[map] presented above.
-
- Note that in some cases, the type for the accumulator is not generalised
- enough based on the result of the first iteration, in which cases annotations
- are needed:
-
- @examples[#:eval ((make-eval-factory '(typed-map) #:lang 'typed/racket))
- (eval:error (foldl (λ (x acc) (cons acc (add1 x))) '() '(1 2 3)))
- (foldl (λ (x [acc : (Rec R (U Null (Pairof R Positive-Index)))])
- (cons acc (add1 x)))
- '()
- '(1 2 3))]}
-
-@defproc[#:kind "syntax"
- (foldr [f (→ A ... Acc Acc)] [init Acc] [l (Listof A)] ...) Acc]{
- Like @orig:foldr from @racketmodname[typed/racket/base] but with better type
- inference for Typed Racket.
-
- This form is implemented in the same way as the overloaded version of
- @racket[map] presented above.
-
- Note that in some cases, the type for the accumulator is not generalised
- enough based on the result of the first iteration, in which cases annotations
- are needed. See the example given for @racket[foldl].}
-\ No newline at end of file
diff --git a/typed-map-doc/info.rkt b/typed-map-doc/info.rkt
@@ -0,0 +1,14 @@
+#lang info
+(define collection "typed-map")
+(define deps '("base"))
+(define build-deps '("scribble-lib"
+ "racket-doc"
+ "typed-racket-doc"))
+(define scribblings '(("scribblings/typed-map.scrbl" ())))
+(define pkg-desc
+ (string-append "Documentation for typed-map-lib, a"
+ " type inference helper for map with Typed/Racket."
+ " Supports afl, un-annotated lambdas and polymorphic"
+ " functions."))
+(define version "1.0")
+(define pkg-authors '("Georges Dupéron"))
diff --git a/typed-map-doc/scribblings/typed-map.scrbl b/typed-map-doc/scribblings/typed-map.scrbl
@@ -0,0 +1,112 @@
+#lang scribble/manual
+@require[scribble/example
+ @for-label[typed-map]]
+
+@title{typed-map}
+@author[@author+email["Georges Dupéron" "georges.duperon@gmail.com"]]
+
+@(module orig racket/base
+ (require scribble/manual
+ (for-label racket/base))
+ (provide orig:map orig:foldl orig:foldr)
+ (define orig:map @racket[map])
+ (define orig:foldl @racket[foldl])
+ (define orig:foldr @racket[foldr]))
+@(require 'orig)
+
+@defmodule[typed-map]
+
+@defproc[#:kind "syntax"
+ (map [f (→ A ... B)] [l (Listof A)] ...) (Listof B)]{
+ Like @orig:map from @racketmodname[typed/racket/base], but with better type
+ inference for Typed Racket.
+
+ When @racket[f] is a literal lambda of the form
+ @racket[(λ (arg ...) body ...)], it is not necessary to specify the type of
+ the arguments, as they will be inferred from the list.
+
+ @examples[#:eval ((make-eval-factory '(typed-map) #:lang 'typed/racket))
+ (map (λ (x) (* x 2)) '(1 2 3))
+ (let ([l '(4 5 6)])
+ (map (λ (x) (* x 2)) l))]
+
+ This enables the use of @racket[#,(hash-lang) #,(racketmodname aful)] for
+ @racket[map] in Typed Racket.
+
+ Furthermore, when @racket[f] is a polymorphic function, type annotations are
+ not needed:
+
+ @examples[#:eval ((make-eval-factory '(typed-map) #:lang 'typed/racket))
+ (map car '([a . 1] [b . 2] [c . 3]))]
+
+ Compare this with the behaviour of @orig:map from
+ @racketmodname[racket/base], which generates a type error:
+
+ @examples[#:eval ((make-eval-factory '() #:lang 'typed/racket))
+ (eval:alts (#,orig:map car '([a . 1] [b . 2] [c . 3]))
+ (eval:error (map car '([a . 1] [b . 2] [c . 3]))))]
+
+ When used as an identifier, the @racket[map] macro expands to the original
+ @orig:map from @racketmodname[typed/racket/base]:
+
+ @examples[#:eval ((make-eval-factory '(typed-map) #:lang 'typed/racket))
+ (eval:alts (require (only-in racket/base [#,orig:map orig:map]))
+ (require (only-in racket/base [map orig:map])))
+ (equal? map orig:map)]
+
+ Note that the implementation expands to a large expression, and makes use of
+ @racket[set!] internally to build the result list. The trick used proceeds as
+ follows:
+ @itemlist[
+ @item{It uses @racket[(reverse (reverse l))] to generalise the type of the
+ list, without having to express that type, so that Type / Racket infers a
+ more general type of the form @racket[(Listof A)], without detecting that the
+ output is identical to the input. An unoptimizable guard prevents the
+ double-reverse from actually being executed, so it does not incur a
+ performance cost.}
+ @item{It uses a
+ @seclink["Named_let" #:doc '(lib "scribblings/guide/guide.scrbl")]{named
+ @racket[let]} to perform the loop. The function @racket[f] is never passed
+ as an argument to another polymorphic function, and is instead directly
+ called with the appropriate arguments. The error message ``Polymorphic
+ function `map' could not be applied to arguments'' is therefore not raised.}
+ @item{To have the most precise and correct types, it uses a named let with a
+ single variable containing the list (with the generalized type). An outer let
+ binds a mutable accumulator, initialized with a single-element list
+ containing the result of applying @racket[f] on the first element of the
+ list. Since all elements of the list belong to the generalized type, the
+ result of calling @racket[f] on any element has the same type, therefore the
+ accumulator has the type @racket[(Listof B)], where @racket[B] is the
+ inferred type of the result of @racket[f].}]}
+
+
+@defproc[#:kind "syntax"
+ (foldl [f (→ A ... Acc Acc)] [init Acc] [l (Listof A)] ...) Acc]{
+ Like @orig:foldl from @racketmodname[typed/racket/base] but with better type
+ inference for Typed Racket.
+
+ This form is implemented in the same way as the overloaded version of
+ @racket[map] presented above.
+
+ Note that in some cases, the type for the accumulator is not generalised
+ enough based on the result of the first iteration, in which cases annotations
+ are needed:
+
+ @examples[#:eval ((make-eval-factory '(typed-map) #:lang 'typed/racket))
+ (eval:error (foldl (λ (x acc) (cons acc (add1 x))) '() '(1 2 3)))
+ (foldl (λ (x [acc : (Rec R (U Null (Pairof R Positive-Index)))])
+ (cons acc (add1 x)))
+ '()
+ '(1 2 3))]}
+
+@defproc[#:kind "syntax"
+ (foldr [f (→ A ... Acc Acc)] [init Acc] [l (Listof A)] ...) Acc]{
+ Like @orig:foldr from @racketmodname[typed/racket/base] but with better type
+ inference for Typed Racket.
+
+ This form is implemented in the same way as the overloaded version of
+ @racket[map] presented above.
+
+ Note that in some cases, the type for the accumulator is not generalised
+ enough based on the result of the first iteration, in which cases annotations
+ are needed. See the example given for @racket[foldl].}
+\ No newline at end of file
diff --git a/LICENSE.txt b/typed-map-lib/LICENSE.txt
diff --git a/README.md b/typed-map-lib/README.md
diff --git a/typed-map-lib/info.rkt b/typed-map-lib/info.rkt
@@ -0,0 +1,11 @@
+#lang info
+(define collection "typed-map")
+(define deps '("base"
+ "typed-racket-lib"))
+(define build-deps '())
+(define pkg-desc
+ (string-append "Type inference helper for map with Typed/Racket."
+ " Supports afl, un-annotated lambdas and polymorphic"
+ " functions."))
+(define version "1.0")
+(define pkg-authors '("Georges Dupéron"))
diff --git a/main.rkt b/typed-map-lib/main.rkt
diff --git a/typed-map-test/info.rkt b/typed-map-test/info.rkt
@@ -0,0 +1,12 @@
+#lang info
+(define collection "typed-map")
+(define deps '("base"
+ "rackunit-lib"
+ "typed-racket-lib"
+ "typed-racket-more"
+ "typed-map-lib"))
+(define build-deps '("aful"))
+(define scribblings '(("scribblings/typed-map.scrbl" ())))
+(define pkg-desc "Tests for typed-map-lib")
+(define version "1.0")
+(define pkg-authors '("Georges Dupéron"))
diff --git a/test/test-map.rkt b/typed-map-test/test/test-map.rkt
diff --git a/typed-map/info.rkt b/typed-map/info.rkt
@@ -0,0 +1,13 @@
+#lang info
+(define collection 'multi)
+(define deps '("typed-map-lib"
+ "typed-map-test"))
+(define implies '("typed-map-lib"
+ "typed-map-test"))
+(define build-deps '())
+(define pkg-desc
+ (string-append "Type inference helper for map with Typed/Racket."
+ " Supports afl, un-annotated lambdas and polymorphic"
+ " functions."))
+(define version "1.0")
+(define pkg-authors '("Georges Dupéron"))