Cleaned up flexible structures implementation. The problem is that compiling the definitions is rather slow (~4 minutes for 10/128 fields), although those can be pre-compiled in advance, and using the functions is rather slow to typecheck (about 0.4s to use a 10/32 constructor), which is more of a problem.

This commit is contained in:
Georges Dupéron 2017-05-18 15:10:33 +02:00
parent 8f13786bf0
commit bf9d5b2328
3 changed files with 60 additions and 39 deletions

12
binarytree.hl.rkt Normal file
View File

@ -0,0 +1,12 @@
#lang type-expander
(provide BinaryTree)
(require (for-syntax syntax/parse
phc-toolkit/aliases))
(define-type-expander BinaryTree
(syntax-parser
[(_ leafⱼ )
;; TODO: implement BinaryTree.
#'(List leafⱼ )]))

View File

@ -1,13 +1,28 @@
#lang type-expander #lang type-expander
(require (lib "phc-graph/flexible-with-generalized-ctor.hl.rkt")) (require "flexible-with-generalized-ctor.hl.rkt"
(provide f g) "binarytree.hl.rkt")
(provide f-4-2 f-8-3)
(builder-f f 4 2) (builder-f f-4-2 4 2)
#;((inst f propagate-τ '|1| Number '|3| String) (ann ((inst f-4-2 propagate-τ '|1| Number '|3| String)
oracle '|1| 100 '|3| "bee") oracle '|1| 100 '|3| "bee")
(BinaryTree
(Promise (Pairof #f Any))
(Promise (Pairof '|1| Number))
(Promise (Pairof #f Any))
(Promise (Pairof '|3| String))))
(builder-f g 8 3) (builder-f f-8-3 8 3)
#;((inst g propagate-τ '|1| Number '|3| String '|7| Symbol) (ann ((inst f-8-3 propagate-τ '|1| Number '|3| String '|7| Symbol)
oracle '|1| 100 '|3| "bee" '|7| 'buzz) oracle '|1| 100 '|3| "bee" '|7| 'buzz)
(BinaryTree
(Promise (Pairof #f Any))
(Promise (Pairof '|1| Number))
(Promise (Pairof #f Any))
(Promise (Pairof '|3| String))
(Promise (Pairof #f Any))
(Promise (Pairof #f Any))
(Promise (Pairof #f Any))
(Promise (Pairof '|7| Symbol))))

View File

@ -9,7 +9,6 @@
꩜chunk[<*> ꩜chunk[<*>
(provide builder-τ (provide builder-τ
None
propagate-τ propagate-τ
oracle oracle
builder-f) builder-f)
@ -20,15 +19,8 @@
racket/list racket/list
racket/function racket/function
subtemplate/override) subtemplate/override)
(for-meta 2 racket/base)) (for-meta 2 racket/base)
"binarytree.hl.rkt")
(struct (T) None ([f : (Promise T)]))
(define-type-expander BinaryTree
(syntax-parser
[(_ leafⱼ )
;; TODO: implement BinaryTree.
#'(List leafⱼ )]))
<propagate-τ> <propagate-τ>
<oracle-τ> <oracle-τ>
@ -70,7 +62,7 @@ form of) the builder function type as follows:
( (code:comment "; Keys and values:") ( (code:comment "; Keys and values:")
{?@ ( Kⱼ (U 'NSymⱼᵢ )) Xⱼ} {?@ ( Kⱼ (U 'NSymⱼᵢ )) Xⱼ}
;; Result type: ;; Result type:
(BinaryTree |<Some or None>| )))] (BinaryTree (Promise |<Some or None>|) )))]
We expect each key ꩜racket[Kⱼ] to be a symbol of the shape ꩜racket[|0|], We expect each key ꩜racket[Kⱼ] to be a symbol of the shape ꩜racket[|0|],
꩜racket[|1|], ꩜racket[|2|] and so on: ꩜racket[|1|], ꩜racket[|2|] and so on:
@ -115,11 +107,12 @@ otherwise. The second element of the pair contains our expected
꩜racket[(Some Xⱼ)] type, but the whole pair is collapsed to ꩜racket[Nothing] ꩜racket[(Some Xⱼ)] type, but the whole pair is collapsed to ꩜racket[Nothing]
when ꩜racket[Kⱼ] is not ꩜racket['NSymᵢ]. when ꩜racket[Kⱼ] is not ꩜racket['NSymᵢ].
We use a similar approach to conditionally produce the ꩜racket[None] element, We use a similar approach to conditionally produce the ꩜racket[None] element
but instead of intersecting ꩜racket[Kⱼ] with ꩜racket['NSymᵢ], we intersect it (which we represent as ꩜racket[#f]), but instead of intersecting ꩜racket[Kⱼ]
with the complement of ꩜racket['NSymᵢ]. Typed Racket lacks the possibility to with ꩜racket['NSymᵢ], we intersect it with the complement of ꩜racket['NSymᵢ].
negate a type, so we manually compute the complement of ꩜racket['NSymᵢ] in the Typed Racket lacks the possibility to negate a type, so we manually compute
set of possible keys (that is, ꩜racket['NSymᵢ ]). the complement of ꩜racket['NSymᵢ] in the set of possible keys (that is,
꩜racket['NSymᵢ ]).
꩜chunk[<builder-τ-with-3> ꩜chunk[<builder-τ-with-3>
#:with NSyms (NSymᵢ ) #:with NSyms (NSymᵢ )
@ -138,7 +131,7 @@ The resulting type should therefore be ꩜racket[Nothing] only if there is no
꩜racket[(List . exceptᵢ)] otherwise. ꩜racket[(List . exceptᵢ)] otherwise.
꩜chunk[|<None if ∀ k ∈ Kⱼ, k ≠ NSymᵢ>| ꩜chunk[|<None if ∀ k ∈ Kⱼ, k ≠ NSymᵢ>|
(None (List { Kᵢⱼ {U 'exceptᵢⱼ }} ))] (Pairof #f (List { Kᵢⱼ {U 'exceptᵢⱼ }} ))]
This approach relies on the fact that occurrences of ꩜racket[Nothing] within This approach relies on the fact that occurrences of ꩜racket[Nothing] within
structs and pairs containing collapse the entire struct or pair type to structs and pairs containing collapse the entire struct or pair type to
@ -163,12 +156,12 @@ To force Typed Racket to propagate ꩜racket[Nothing] outwards as much as
we need, we intersect the whole form with a polymorphic type ꩜racket[A]: we need, we intersect the whole form with a polymorphic type ꩜racket[A]:
꩜hlite[|<builder-function-type'>| ꩜hlite[|<builder-function-type'>|
{/((+ _ / _ _)( _ _ ooo (bt + ( / _ + A) / _)))} {/((+ _ / _ _)( _ _ ooo (bt (p + ( / _ + A)) / ooo)))}
( (A {?@ Kⱼ Xⱼ} ) ( (A {?@ Kⱼ Xⱼ} )
( (code:comment "; Keys and values:") ( (code:comment "; Keys and values:")
{?@ ( Kⱼ (U 'NSymⱼᵢ )) Xⱼ} {?@ ( Kⱼ (U 'NSymⱼᵢ )) Xⱼ}
;; Result type: ;; Result type:
(BinaryTree (|<Some or None>| A) )))] (BinaryTree (Promise (|<Some or None>| A)) )))]
The type ꩜racket[propagate-τ] defined below is used to instantiate ꩜racket[A], The type ꩜racket[propagate-τ] defined below is used to instantiate ꩜racket[A],
and is carefully picked so that its intersection will in no way change the and is carefully picked so that its intersection will in no way change the
@ -180,8 +173,8 @@ instantiated.
꩜chunk[<propagate-τ> ꩜chunk[<propagate-τ>
(define-type propagate-τ (define-type propagate-τ
(U (Pairof Any Any) (U (Pairof Symbol Any)
(None (Listof Any))))] (Pairof #f (Listof Symbol))))]
;Use chunkref instead of ꩜racket[|<Some or None>|] ? ;Use chunkref instead of ꩜racket[|<Some or None>|] ?
@ -199,8 +192,8 @@ upgrade.
꩜chunk[<oracle-τ> ꩜chunk[<oracle-τ>
(define-type (oracle-τ A) (define-type (oracle-τ A)
( (B) ( ( B ( (B) ( ( B
(U (Pairof Any Any) (U (Pairof Symbol Any)
(None (Listof Any)))) (Pairof #f (Listof Symbol))))
( A B))))] ( A B))))]
The oracle does nothing more than return its argument unchanged: The oracle does nothing more than return its argument unchanged:
@ -220,7 +213,7 @@ oracle:
(code:comment "; Keys and values:") (code:comment "; Keys and values:")
{?@ ( Kⱼ (U 'NSymⱼᵢ )) Xⱼ} {?@ ( Kⱼ (U 'NSymⱼᵢ )) Xⱼ}
;; Result type: ;; Result type:
(BinaryTree (|<Some or None>| A) )))] (BinaryTree (Promise (|<Some or None>| A)) )))]
@ -243,11 +236,12 @@ oracle:
꩜chunk[<builder-function-implementation> ꩜chunk[<builder-function-implementation>
(: name |<builder-function-type''>| #;(builder-τ n m)) (: name |<builder-function-type''>| #;(builder-τ n m))
(define (name oracle {?@ kⱼ xⱼ} ) (define (name oracle {?@ kⱼ xⱼ} )
(list (cond (list (delay
[((make-predicate 'NSymᵢⱼ) kᵢⱼ) (cond
((inst oracle (Pairof ( Kᵢⱼ 'NSymᵢⱼ) Xᵢⱼ)) (cons kᵢⱼ xᵢⱼ))] [((make-predicate 'NSymᵢⱼ) kᵢⱼ)
((inst oracle (Pairof ( Kᵢⱼ 'NSymᵢⱼ) Xᵢⱼ)) (cons kᵢⱼ xᵢⱼ))]
[else
((inst oracle (None (List ( Kᵢⱼ (U 'exceptᵢⱼ )) ))) [else
(None (delay (list kᵢⱼ ))))]) ((inst oracle (Pairof #f (List ( Kᵢⱼ (U 'exceptᵢⱼ )) )))
(cons #f (list kᵢⱼ )))]))
))] ))]