[racket-dev] What is the policy on what is included in the core libraries?

2015-02-16 Thread Alexis King
I was just thinking today that I would, for example, find it useful to have a 
(zip ...) function in racket/list that would be equivalent to (map list ...). 
Users coming from a Haskell background might even find it useful to have a 
zip-with function that is simply an alias for map. Admittedly, these are rather 
trivial, but (especially in the first case) I think they’d still be useful.

I am all for avoiding feature creep and code bloat, but Racket’s “batteries 
included” approach seems to make functions like these prime candidates for 
libraries like racket/list. As long as they’re not in racket/base, they seem 
fairly harmless, especially considering they would only be needed at 
compile-time.

Should I even consider adding things like this, or is the consensus that the 
libraries are mostly sufficient as-is?

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-dev+unsubscr...@googlegroups.com.
To post to this group, send email to racket-...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/racket-dev/5D941DB1-8A55-4A41-98A2-A3BE1BFE6D40%40gmail.com.
For more options, visit https://groups.google.com/d/optout.


Re: [racket-dev] A proposal for parametric opaque types in Typed Racket

2015-01-30 Thread Alexis King
Okay, now I see what you’re saying. That’s a reasonable point, and it’s worth 
considering. Thanks for bearing with me.

> On Jan 30, 2015, at 13:24, Alexander D. Knauth  wrote:
> 
> 
> On Jan 30, 2015, at 3:59 PM, Alexis King  <mailto:lexi.lam...@gmail.com>> wrote:
> 
>> No, the typechecker can’t make any assumptions about the results of opaque 
>> types. If you explicitly instantiate a Posn with the type Real, the 
>> typechecker should only guarantee the result will be Real. Annotate the type 
>> as (U 1 2), though, and obviously it would need to ensure that remains 
>> invariant.
> 
> How about this program:
> untyped.rkt:
> #lang racket
> (provide (all-defined-out))
> (define (make-posn x y) (list 3 y)) ; bad
> typed.rkt:
> #lang typed/racket
> ; make Posn parametric
> (define-type (Posn X Y) (List X Y))
> (require/typed "untyped.rkt"
>[make-posn (All (X Y) X Y -> (Posn X Y))])
> (: p : (Posn Real Real))
> (define p (make-posn 1 2))
> This gives this error:
> . . make-posn: broke its contract
>   promised: X3
>   produced: 3
>   in: the car of
>   the range of
>   (parametric->/c
>(X3 Y4)
>(->*
> (X3 Y4)
> ()
> (values (cons/c X3 (cons/c Y4 g6)
>   contract from: (interface for make-posn)
>   blaming: (interface for make-posn)
>(assuming the contract is correct)
>   at: …./typed.rkt:5.16
> 
> I think it’s a good thing that it checks that it actually gives you the value 
> that you gave it, and not just something like 3 even if it happens to match 
> the type you want.  And I think parametric opaque types should behave in a 
> similar way, and to do that you would need the opaque value to be wrapped in 
> another opaque structure, which would store either the contracts or the set 
> of values that would pass the contracts or something like that.  
> 
>> 
>>> On Jan 30, 2015, at 12:30, Alexander D. Knauth >> <mailto:alexan...@knauth.org>> wrote:
>>> 
>>> 
>>> On Jan 30, 2015, at 1:53 PM, Alexis King >> <mailto:lexi.lam...@gmail.com>> wrote:
>>> 
>>>> No, it doesn’t need to be wrapped in an opaque structure. Wrapping it in 
>>>> an opaque structure would add a layer of indirection for absolutely no 
>>>> gain. Remember, the value itself is already, by definition, opaque. The 
>>>> only way typed code can manipulate the value is by passing it to other 
>>>> functions imported via require/typed.
>>>> 
>>>> This means that contracts only need to be generated wherever those 
>>>> functions are called. This can be done without wrapping or unwrapping 
>>>> anything because all the information required to generate those contracts 
>>>> is known at expansion-time. The typechecker simply needs to insert the 
>>>> relevant contracts at the relevant locations.
>>> 
>>> Imagine a program like this:
>>> #lang typed/racket
>>> (require typed/lang/posn)
>>> (: p : (Posn Real Real)) ; I’m assuming Posn is parametric over 2 tvars, 
>>> not 1
>>> (define p (posn 1 2))
>>> (: x : Real)
>>> (define x (posn-x p))
>>> As far as the type checker would check, it would check that the result of 
>>> posn-x is a Real, but I think that the runtime contract it should also 
>>> check that it returns 1, because posn could have been instantiated as (Posn 
>>> 1 2).
>>> #lang typed/racket
>>> (require typed/lang/posn/mutable) ; like typed/lang/posn, but providing 
>>> mutation too
>>> (: p : (Posn Real Real))
>>> (define p (posn 1 2))
>>> (: x : Real)
>>> (define x (posn-x p))
>>> (set-posn-x! p 3)
>>> (: x2 : Real)
>>> (define x2 (posn-x p))
>>> Here, even though the type checker only cares that it’s a number, it should 
>>> check that x2 definition returns either 1 or 3, since both were provided as 
>>> x values for the posn p.
>>> 
>>> For it to keep track of these at runtime, (and it would have to be runtime) 
>>> the contracts would have to be with the actual posn value in an opaque 
>>> structure, which would have contracts sort of like (new-∀/c) that would 
>>> check these things, although I don’t think it would have to wrap the inner 
>>> values, but just record them so that when posn-x is called on one of these 
>>> things, it checks that it was one of the values that was passed in to 
>>> either a constructor or setter function.  
>>> 
>>>>

Re: [racket-dev] A proposal for parametric opaque types in Typed Racket

2015-01-30 Thread Alexis King
No, it doesn’t need to be wrapped in an opaque structure. Wrapping it in an 
opaque structure would add a layer of indirection for absolutely no gain. 
Remember, the value itself is already, by definition, opaque. The only way 
typed code can manipulate the value is by passing it to other functions 
imported via require/typed.

This means that contracts only need to be generated wherever those functions 
are called. This can be done without wrapping or unwrapping anything because 
all the information required to generate those contracts is known at 
expansion-time. The typechecker simply needs to insert the relevant contracts 
at the relevant locations.

> On Jan 30, 2015, at 07:27, Alexander D. Knauth  wrote:
> 
>  
>  
>  
> On Thu, Jan 29, 2015, at 09:03 PM, Alexis King wrote:
>> It isn’t wrapped in an opaque structure. That wasn’t a part of my proposal, 
>> and while I didn’t think of it until you brought it up, I still think it’s 
>> unnecessary and doesn’t add any convenience.
>  
> I think the opaque structures would be necessary for the kind of "sharing 
> wrappers between functions" that you describe just before section 2.1, except 
> that instead of the sub-values being wrapped on the untyped side, the whole 
> thing is wrapped on the typed side, and there is a contract that wraps it and 
> unwraps it when it goes from untyped to typed and back.  
>  
> For parametric types, they have to also work if the type was constrained to 
> the exact set of values that were provided, which means that if you provide 
> two numbers, say 1 and 2, it has to return a posn with not just any two 
> numbers, but values of the type (U 1 2), since A could have been constrained 
> to (U 1 2).  So it has to be wrapped somehow, and I think wrapping it on the 
> typed side makes more sense.  
>  
>> Perhaps I’m not understanding you properly, but your “one-length string” 
>> idea sounds like it has little to do with this opaque type problem and more 
>> to do with the fact that you want refinement types in Typed Racket. I do, 
>> too! But I don’t think hacking the opaque type system is going to help you 
>> with that.
>  
> Well, yeah, refinement types would be the "real" solution for this particular 
> example, but if I do want to constrain it to strings of length 1, opaque 
> types are the only option for now, and they actually work fine.  My point was 
> you couldn't do this type of thing with the opaque structures and you would 
> probably get weird errors if you tried.  (See below because there might be a 
> solution?)
>  
>> (Also, as for the box example, I’m actually a little surprised that doesn’t 
>> contract error. Seems like a bug to me, but perhaps I’m missing some 
>> idiosyncrasies of the type system. Either way, it’s precisely that kind of 
>> craziness I was referring to when I compared casting parametric opaque types 
>> to casting mutable types.)
>  
> There is a bug report for it here, and the solution proposed by Sam 
> Tobin-Hochstadt would be for cast to generate 2 contracts, one for the 
> original type, one for the new type, but that never got implemented.  
> http://bugs.racket-lang.org/query/?cmd=view&pr=13626 
> <http://bugs.racket-lang.org/query/?cmd=view&pr=13626>
>  
> Actually now that I think about it the two-contract solution might be able to 
> solve the previous problem, since the original contract could unwrap the 
> value before it is passed to the new contract?  I'm not sure though.  The 
> value inside the cast would be from the typed side, then it is passed through 
> the orig contract as if it were going to the typed side, which would unwrap 
> it, and then that unwrapped value would be passed to the new contract as if 
> it were flowing from the untyped side to the typed side.  
>  
>>  
>>> On Jan 29, 2015, at 20:50, Alexander D. Knauth >> <mailto:alexan...@knauth.org>> wrote:
>>>  
>>>  
>>> On Jan 29, 2015, at 11:34 PM, Alexis King >> <mailto:lexi.lam...@gmail.com>> wrote:
>>>  
>>>>> But the problem is that if it’s an opaque type then it can’t unwrap it 
>>>>> once the value is returned from make-posn.
>>>>  
>>>> Yes, that’s precisely the problem. Your point about implementing 
>>>> everything as single-valued structs on the typed side is an interesting 
>>>> one, though I don’t think it ultimately solves any problems. The fact that 
>>>> the typed side knowsnothingabout the contents of the value is what makes 
>>>> this such a tricky problem.
>>>>  
>>>> As for this:
>>>>  
>>>>> But then you co

Re: [racket-dev] A proposal for parametric opaque types in Typed Racket

2015-01-29 Thread Alexis King
It isn’t wrapped in an opaque structure. That wasn’t a part of my proposal, and 
while I didn’t think of it until you brought it up, I still think it’s 
unnecessary and doesn’t add any convenience.

Perhaps I’m not understanding you properly, but your “one-length string” idea 
sounds like it has little to do with this opaque type problem and more to do 
with the fact that you want refinement types in Typed Racket. I do, too! But I 
don’t think hacking the opaque type system is going to help you with that.

(Also, as for the box example, I’m actually a little surprised that doesn’t 
contract error. Seems like a bug to me, but perhaps I’m missing some 
idiosyncrasies of the type system. Either way, it’s precisely that kind of 
craziness I was referring to when I compared casting parametric opaque types to 
casting mutable types.)

> On Jan 29, 2015, at 20:50, Alexander D. Knauth  wrote:
> 
> 
> On Jan 29, 2015, at 11:34 PM, Alexis King  <mailto:lexi.lam...@gmail.com>> wrote:
> 
>>> But the problem is that if it’s an opaque type then it can’t unwrap it once 
>>> the value is returned from make-posn.
>> 
>> Yes, that’s precisely the problem. Your point about implementing everything 
>> as single-valued structs on the typed side is an interesting one, though I 
>> don’t think it ultimately solves any problems. The fact that the typed side 
>> knows nothing about the contents of the value is what makes this such a 
>> tricky problem.
>> 
>> As for this:
>> 
>>> But then you couldn’t do any operations on it except those that you use 
>>> import with require/typed, right?
>> 
>> That’s completely correct. That’s why it’s “opaque.”
>> 
>>> And what happens if you use cast on one of these things?
>> 
>> That’s a little more interesting. Using cast on an object of this type would 
>> never fail (unless, of course, it didn’t actually satisfy the basic posn? 
>> predicate), but it would possibly introduce failures in the future since it 
>> would affect the contracts generated for posn-x and posn-y, for example.
>> 
>> To make that more clear, casting a (Posn Real) to a (Posn String) would work 
>> fine until you tried to call posn-x on the instance, in which case it would 
>> raise a contract error. Note that this isn’t really any different from 
>> casting mutable data types.
> 
> But if it were wrapped in an opaque structure, then that structure wouldn’t 
> satisfy the posn? predicate, unless of course the posn? predicate has a 
> contract that unwraps it.  So all of the operations on it would have to have 
> contracts that would unwrap it.  This might actually make sense if the type 
> is meant to be actually opaque, but if it’s an opaque type that represents a 
> normal non-opaque value, then it will still work as an opaque type, but it 
> won’t be a normal non-opaque value anymore on the typed side.  
> 
> But the reason I asked about cast was because normally I can use cast with a 
> value that has an opaque type, but it’s wrapped on the typed side in this 
> opaque structure, then the contracts on the cast would see this opaque 
> structure instead of the actual value.  
> 
> I’m thinking of an opaque typed representing a string with length 1, which I 
> can use as long as I use either (cast x String) or (assert x string?) 
> whenever I pass it to a string operation.  But if it were an opaque type, I 
> don’t think I could do that.  There could be a 1string->string function that 
> could take one of these 1strings and convert it to a string, but that seems 
> like it should be unnecessary, but made necessary by this opaque structure 
> thing.  
> 
> And for “this isn’t really any different from casting mutable data types,” 
> look at this:
> #lang typed/racket
> (: b : (Boxof Number))
> (define b (box 1))
> (set-box! (cast b (Boxof (U Number String))) "I am a string")
> (ann (unbox b) Number) ;"I am a string” ; not a contract error
> 
> 
>> 
>>> On Jan 29, 2015, at 20:20, Alexander D. Knauth >> <mailto:alexan...@knauth.org>> wrote:
>>> 
>>> Furthermore, even if the wrappers were shared between functions, untyped 
>>> code would recieved wrapped values, which would render them quite useless.
>>> 
>>> If it’s not an opaque type, but something like a list, then this works, and 
>>> the untyped code receiving wrapped values isn’t a problem here:
>>> #lang typed/racket
>>> ; make Posn parametric
>>> (define-type (Posn A) (List A A))
>>> (provide Posn)
>>> (require/typed/provide
>>>  "untyped.rkt"
>>>  [make-posn (All (A) A A -> (Posn A))]
>>> 

Re: [racket-dev] A proposal for parametric opaque types in Typed Racket

2015-01-29 Thread Alexis King
> But the problem is that if it’s an opaque type then it can’t unwrap it once 
> the value is returned from make-posn.

Yes, that’s precisely the problem. Your point about implementing everything as 
single-valued structs on the typed side is an interesting one, though I don’t 
think it ultimately solves any problems. The fact that the typed side knows 
nothing about the contents of the value is what makes this such a tricky 
problem.

As for this:

> But then you couldn’t do any operations on it except those that you use 
> import with require/typed, right?

That’s completely correct. That’s why it’s “opaque.”

> And what happens if you use cast on one of these things?

That’s a little more interesting. Using cast on an object of this type would 
never fail (unless, of course, it didn’t actually satisfy the basic posn? 
predicate), but it would possibly introduce failures in the future since it 
would affect the contracts generated for posn-x and posn-y, for example.

To make that more clear, casting a (Posn Real) to a (Posn String) would work 
fine until you tried to call posn-x on the instance, in which case it would 
raise a contract error. Note that this isn’t really any different from casting 
mutable data types.

> On Jan 29, 2015, at 20:20, Alexander D. Knauth  wrote:
> 
> Furthermore, even if the wrappers were shared between functions, untyped code 
> would recieved wrapped values, which would render them quite useless.
> 
> If it’s not an opaque type, but something like a list, then this works, and 
> the untyped code receiving wrapped values isn’t a problem here:
> #lang typed/racket
> ; make Posn parametric
> (define-type (Posn A) (List A A))
> (provide Posn)
> (require/typed/provide
>  "untyped.rkt"
>  [make-posn (All (A) A A -> (Posn A))]
>  [posn-x (All (A) (Posn A) -> A)]
>  [posn-y (All (A) (Posn A) -> A)]
>  [real-posn? [(Posn Any) -> Boolean]])
> > (define p (make-posn 1 2))
> (make-posn # #) ; a printf that I put in make-posn from “untyped.rkt"
> > p
> - : (Listof Positive-Byte) [more precisely: (List Positive-Byte 
> Positive-Byte)]
> '(1 2) ; unwrapped
> > (posn-x p)
> - : Integer [more precisely: Positive-Byte]
> 1
> > (posn-y p)
> - : Integer [more precisely: Positive-Byte]
> 2
> > (real-posn? p)
> - : Boolean
> #t
> 
> Even though for a short time it's wrapped, it’s unwrapped as soon as 
> make-posn returns, and then after that if it flows into untyped code again 
> it’s not wrapped and functions like real-posn? work fine.  
> 
> But the problem is that if it’s an opaque type then it can’t unwrap it once 
> the value is returned from make-posn.
> 
> And I don’t think parametric opaque types could solve this unless all posns 
> themselves were wrapped with an opaque struct on the typed side, which I 
> guess does make sense now that I think about it.  But then you couldn’t do 
> any operations on it except those that you use import with require/typed, 
> right?  Or not?  And what happens if you use cast on one of these things?
> 
> 
> On Jan 29, 2015, at 9:25 PM, Alexis King  <mailto:lexi.lam...@gmail.com>> wrote:
> 
>> I recently ran into a problem in which opaque types (types imported from 
>> untyped code) cannot by parameterized by Typed Racket. I initially 
>> encountered this problem in my attempt to port 2htdp/image to TR 
>> <https://github.com/lexi-lambda/racket-2htdp-typed/issues/1>.
>> 
>> After some further consideration, I’m interested in adding support to make 
>> something like this possible, which would certainly have additional benefits 
>> beyond this specific use-case. I’ve outlined my proposal here:
>> http://lexi-lambda.github.io/racket-parametric-opaque-types/ 
>> <http://lexi-lambda.github.io/racket-parametric-opaque-types/>
>> 
>> Any feedback, suggestions, or advice would be appreciated, especially from 
>> those who are familiar with Typed Racket’s internals.
>> 
>> Thank you,
>> Alexis
>> _
>>  Racket Developers list:
>>  http://lists.racket-lang.org/dev <http://lists.racket-lang.org/dev>
> 

_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] A proposal for parametric opaque types in Typed Racket

2015-01-29 Thread Alexis King
I think you’re reading too far into what I’m proposing, though I admit I 
probably didn’t give enough context. I’ve been talking with Sam about this 
issue on IRC, so he knows what I’m talking about, but I’ll try and clarify here.

This entire thing is just a fix for the problem described in Section 2 
<http://lexi-lambda.github.io/racket-parametric-opaque-types/#(part._.Extending_parametricity_to_opaque_types)>.
 When using require/typed to import “opaque” types from untyped code, the 
imported types cannot be polymorphic. This entire proposal is simply a way to 
make that possible.

In Section 2.1, A is used in a number of places, but it is just a type 
parameter. See the typed struct definition in Section 1. A does not refer to a 
specific type but any type. Posn essentially becomes a new type combinator than 
can make new types by supplying it with any other type.

The other functions imported in Section 2.1 simply make use of Typed Racket’s 
polymorphic type utilities to make use of the fact that Posn is now a 
polymorphic type. The concepts here are simple. No semantics are being changed, 
it’s just extending parameterization to opaque types.

Sections 2.3 and 2.2, in contrast, are simply describing mechanisms for 
implementing the functionality outlined in 2.1.

Now to answer your points.

> - Should an A only be a base type like String or Symbol

A can by any type. It’s a type parameter. (Posn A) is like (Boxof A).

> - Do you mean to infer the type of the first thing put into the struct as the 
> exact type for everything else?

No, not really. Remember that Posn is an opaque type. TR has no idea it’s 
actually implemented as a struct. Perhaps the JSExpr example given in Section 3 
will help to illustrate that generality. This will just leverage the existing 
polymorphic type inference mechanisms TR already provides.

> - Would "first class members" prevent me from filling a struct with members 
> of (define-type (Option A) (U 'None (Some A))), where "Some" is a struct with 
> one field?

No, as I said, you can supply any type for A. By “first class member” of the 
type system, I simply meant that these types would have to be built-in to TR as 
a special case—they cannot be derived from the existing type constructs 
provided by TR. This is similar to how structure types are “first class” in 
TR—the struct form is “magical” and cannot be reimplemented in terms of other 
TR primitives.

I hope that helps to make things a little more clear.

> On Jan 29, 2015, at 19:44, Benjamin Greenman  wrote:
> 
> This has bothered me too, but I've realized that I was on the wrong track.
> 
> The string "a" and symbol 'b are not different types. A struct (Foo "a" 'b), 
> or (list "a" 'b), is a homogeneous data structure of type (U String Symbol) 
> just like Alexander said. This really upsets me -- I like the Hindley Milner 
> world where the compiler warns me if I make a list [1, "two"] and forces me 
> to wrap the int and string into a new datatype. But Typed Racket is not HM.
> 
> About the proposal, I'm confused about what the syntax in Section 2.1 should 
> do -- what is a "first class member of Typed Racket's type system"?
> - Should an A only be a base type like String or Symbol
> - Do you mean to infer the type of the first thing put into the struct as the 
> exact type for everything else?
> - Would "first class members" prevent me from filling a struct with members 
> of (define-type (Option A) (U 'None (Some A))), where "Some" is a struct with 
> one field?
> 
> I totally agree that "something needs fixing", but I'm not sure what.
> 
> 
> 
> On Thu, Jan 29, 2015 at 10:13 PM, Alexis King  <mailto:lexi.lam...@gmail.com>> wrote:
> Or Any for that matter. I know. The fact that it could be literally anything 
> was sort of the point.
> 
>> On Jan 29, 2015, at 19:10, Alexander D. Knauth > <mailto:alexan...@knauth.org>> wrote:
>> 
>> Um, for this:
>> (module 
>> <http://docs.racket-lang.org/reference/module.html#%28form._%28%28quote._~23~25kernel%29._module%29%29>
>>  typed typed/racket/base
>> (provide 
>> <http://docs.racket-lang.org/reference/require.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._provide%29%29>
>>  (struct-out 
>> <http://docs.racket-lang.org/reference/require.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._struct-out%29%29>
>>  Foo))
>> (struct 
>> <http://docs.racket-lang.org/ts-reference/special-forms.html#%28form._%28%28lib._typed-racket%2Fbase-env%2Fprims..rkt%29._struct%29%29>
>>  [A] Foo ([x : 
>> <http://docs.racket-lang.org/ts-reference/special-forms.html#%28form._%2

Re: [racket-dev] A proposal for parametric opaque types in Typed Racket

2015-01-29 Thread Alexis King
Or Any for that matter. I know. The fact that it could be literally anything 
was sort of the point.

> On Jan 29, 2015, at 19:10, Alexander D. Knauth  wrote:
> 
> Um, for this:
> (module 
> <http://docs.racket-lang.org/reference/module.html#%28form._%28%28quote._~23~25kernel%29._module%29%29>
>  typed typed/racket/base
> (provide 
> <http://docs.racket-lang.org/reference/require.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._provide%29%29>
>  (struct-out 
> <http://docs.racket-lang.org/reference/require.html#%28form._%28%28lib._racket%2Fprivate%2Fbase..rkt%29._struct-out%29%29>
>  Foo))
> (struct 
> <http://docs.racket-lang.org/ts-reference/special-forms.html#%28form._%28%28lib._typed-racket%2Fbase-env%2Fprims..rkt%29._struct%29%29>
>  [A] Foo ([x : 
> <http://docs.racket-lang.org/ts-reference/special-forms.html#%28form._%28%28lib._typed-racket%2Fbase-env%2Fprims..rkt%29._~3a%29%29>
>  A] [y : 
> <http://docs.racket-lang.org/ts-reference/special-forms.html#%28form._%28%28lib._typed-racket%2Fbase-env%2Fprims..rkt%29._~3a%29%29>
>  A]) #:transparent))
> 
> (Foo "a" 'b)
> Should be fine because Foo could be instantiated at the type (U String 
> Symbol).
> 
> On Jan 29, 2015, at 9:25 PM, Alexis King  <mailto:lexi.lam...@gmail.com>> wrote:
> 
>> I recently ran into a problem in which opaque types (types imported from 
>> untyped code) cannot by parameterized by Typed Racket. I initially 
>> encountered this problem in my attempt to port 2htdp/image to TR 
>> <https://github.com/lexi-lambda/racket-2htdp-typed/issues/1>.
>> 
>> After some further consideration, I’m interested in adding support to make 
>> something like this possible, which would certainly have additional benefits 
>> beyond this specific use-case. I’ve outlined my proposal here:
>> http://lexi-lambda.github.io/racket-parametric-opaque-types/ 
>> <http://lexi-lambda.github.io/racket-parametric-opaque-types/>
>> 
>> Any feedback, suggestions, or advice would be appreciated, especially from 
>> those who are familiar with Typed Racket’s internals.
>> 
>> Thank you,
>> Alexis
>> _
>>  Racket Developers list:
>>  http://lists.racket-lang.org/dev <http://lists.racket-lang.org/dev>
> 

_
  Racket Developers list:
  http://lists.racket-lang.org/dev


[racket-dev] A proposal for parametric opaque types in Typed Racket

2015-01-29 Thread Alexis King
I recently ran into a problem in which opaque types (types imported from 
untyped code) cannot by parameterized by Typed Racket. I initially encountered 
this problem in my attempt to port 2htdp/image to TR 
.

After some further consideration, I’m interested in adding support to make 
something like this possible, which would certainly have additional benefits 
beyond this specific use-case. I’ve outlined my proposal here:
http://lexi-lambda.github.io/racket-parametric-opaque-types/ 


Any feedback, suggestions, or advice would be appreciated, especially from 
those who are familiar with Typed Racket’s internals.

Thank you,
Alexis_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] In Typed Racket, struct declarations do not work in an internal definition context

2015-01-24 Thread Alexis King
Yes, I’d considered that point, and yes, it makes sense. Anyway, the situation 
in which I was trying to do something like this ended up being unnecessary, so 
I don’t even have a valid use-case anymore. I think it’s probably okay to leave 
it as-is unless someone can come up with a useful reason to care.

> On Jan 24, 2015, at 09:24, Sam Tobin-Hochstadt  wrote:
> 
> On Thu, Jan 22, 2015 at 3:57 PM, Alexis King  wrote:
>> 
>> I can work around this in a variety of ways—I can extract this into an
>> untyped module and use require/typed, I can use vectors to “fake” structs
>> and provide an appropriate interface, etc. Still, I wonder if there are any
>> plans to resolve this type of problem? Since it seems to be an issue with
>> how TR handles types at its core, I’m not even sure how feasible it would
>> be.
> 
> 
> I don't currently have plans to work on this problem. The big issue is
> that Racket structs are what's called "generative", meaning that each
> time you execute a struct declaration, you get a different struct
> type. Thus it's not at all clear what the right type should be for
> your `make-me-a-struct` function, and type systems that do allow this
> sort of thing (such as ML) would reject this particular use.
> 
> Can you say more about the specific issue you're having? There might
> be a different way around it.
> 
> Sam


_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] In Typed Racket, struct declarations do not work in an internal definition context

2015-01-24 Thread Alexis King
I haven’t dug deep enough into the TR code to know for sure, but I think the 
difference is that structs declare fundamentally new types, whereas inline type 
definitions only declare type aliases. Whether or not this is actually the 
problem is unclear—I don’t know TR well enough to answer that.

> On Jan 23, 2015, at 21:23, Alexander D. Knauth  wrote:
> 
> There’s a bug report about this here:
> http://bugs.racket-lang.org/query/?cmd=view&pr=14524 
> <http://bugs.racket-lang.org/query/?cmd=view&pr=14524>
> Though I notice it gives a different error message now.
> But why should structure type declarations being a module-wide construct?
> Internal function definitions work, and internal type definitions work, so 
> why shouldn’t internal structure definitions?
> 
> 
> On Jan 22, 2015, at 3:57 PM, Alexis King  <mailto:lexi.lam...@gmail.com>> wrote:
> 
>> Simple enough. This works:
>> 
>> #lang racket
>> 
>> (define (make-me-a-struct)
>>   (struct foo ())
>>   (foo))
>> 
>> (make-me-a-struct) ; => #
>> 
>> This does not:
>> 
>> #lang typed/racket
>> 
>> (define (make-me-a-struct)
>>   (struct foo ())
>>   (foo)) ; error: cannot apply a function with unknown arity
>> 
>> (make-me-a-struct)
>> 
>> This problem makes sense. Type declarations seem to be a module-wide 
>> construct, so a type that should be scoped to a single function doesn’t 
>> work. I’m running into this issue when trying to create an executable struct 
>> using define-struct/exec from within a macro, which doesn’t work due to this 
>> particular problem.
>> 
>> I can work around this in a variety of ways—I can extract this into an 
>> untyped module and use require/typed, I can use vectors to “fake” structs 
>> and provide an appropriate interface, etc. Still, I wonder if there are any 
>> plans to resolve this type of problem? Since it seems to be an issue with 
>> how TR handles types at its core, I’m not even sure how feasible it would be.
>> _
>>  Racket Developers list:
>>  http://lists.racket-lang.org/dev <http://lists.racket-lang.org/dev>
> 

_
  Racket Developers list:
  http://lists.racket-lang.org/dev


[racket-dev] In Typed Racket, struct declarations do not work in an internal definition context

2015-01-22 Thread Alexis King
Simple enough. This works:

#lang racket

(define (make-me-a-struct)
  (struct foo ())
  (foo))

(make-me-a-struct) ; => #

This does not:

#lang typed/racket

(define (make-me-a-struct)
  (struct foo ())
  (foo)) ; error: cannot apply a function with unknown arity

(make-me-a-struct)

This problem makes sense. Type declarations seem to be a module-wide construct, 
so a type that should be scoped to a single function doesn’t work. I’m running 
into this issue when trying to create an executable struct using 
define-struct/exec from within a macro, which doesn’t work due to this 
particular problem.

I can work around this in a variety of ways—I can extract this into an untyped 
module and use require/typed, I can use vectors to “fake” structs and provide 
an appropriate interface, etc. Still, I wonder if there are any plans to 
resolve this type of problem? Since it seems to be an issue with how TR handles 
types at its core, I’m not even sure how feasible it would be._
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] [racket] Implementing contracts for async channels

2015-01-19 Thread Alexis King
I already used blame-add-context, but the message I used wasn’t very good, so 
I’ve improved it. If everything else looks good, feel free to merge this 
whenever you get the chance!

> On Jan 19, 2015, at 15:52, Robby Findler  wrote:
> 
> Ah: one other note. When you do something like this:
> 
> ((contract (-> (list/c (box/c integer?)) any)
>   (λ (x) (unbox (car x)))
>   'pos 'neg)
> (list (box "not an integer")))
> 
> you get an error message that has this text in the middle:
> 
>  in: the content of
>  the 1st element of
>  the 1st argument of
>  (-> (list/c (box/c integer?)) any)
> 
> This path information is collected in the blame records.
> 
> So, instead of passing along just the blame record you got, call
> "blame-add-context" so you get some stuff in that portion of the error
> message.
> 
> Maybe "a value passed on" or something like that would be a good
> phrase? I usually look at a few examples to pick something.
> 
> Otherwise, this looks good to merge to me (but I don't use the
> generics as much as I should so if you wanted to you could try asking
> for someone specifically knowledgeable to look there).
> 
> If you don't, I can push the commit to the appropriate repo. Let me know.
> 
> Robby
> 
> 
> 
> On Mon, Jan 19, 2015 at 5:44 PM, Alexis King  wrote:
>> Yes, there are tests, and you can see them here.
>> 
>> On Jan 19, 2015, at 13:29, Robby Findler 
>> wrote:
>> 
>> This seemed okay, but just a quick read of the code. But did I miss
>> the test cases? (I just followed the link upthread -- sorry if I need
>> to look somewhere else too.)
>> 
>> Robby
>> 
>> 
>> On Mon, Jan 19, 2015 at 3:15 PM, Alexis King  wrote:
>> 
>> Any update on this? If there’s anything that still needs to be changed, let
>> me know—otherwise, I’ll patiently wait for the process to run its course.
>> Just checking in.
>> 
>> On Jan 16, 2015, at 10:15, Alexis King  wrote:
>> 
>> Ah, that makes sense, fixed.
>> 
>> On Jan 16, 2015, at 05:37, Robby Findler 
>> wrote:
>> 
>> One comment. The contract combinators are curried so that you can do
>> work on the partial applications. So don't write this:
>> 
>> (define ho-val-first-projection
>> impersonate/chaperone-async-channel) ctc) blame) val)
>> 
>> instead try to do some work earlier, when you first can. (The most
>> important thing is to minimize the work done after you get the 'val'
>> argument.)
>> 
>> Robby
>> 
>> 
>> 
>> 
>> _
>> Racket Developers list:
>> http://lists.racket-lang.org/dev
>> 
>> 


_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] [racket] Implementing contracts for async channels

2015-01-19 Thread Alexis King
Yes, there are tests, and you can see them here 
<https://github.com/plt/racket/pull/860/files#diff-9383600c097f090324382317068c6187R1>.

> On Jan 19, 2015, at 13:29, Robby Findler  wrote:
> 
> This seemed okay, but just a quick read of the code. But did I miss
> the test cases? (I just followed the link upthread -- sorry if I need
> to look somewhere else too.)
> 
> Robby
> 
> 
> On Mon, Jan 19, 2015 at 3:15 PM, Alexis King  wrote:
>> Any update on this? If there’s anything that still needs to be changed, let 
>> me know—otherwise, I’ll patiently wait for the process to run its course. 
>> Just checking in.
>> 
>>> On Jan 16, 2015, at 10:15, Alexis King  wrote:
>>> 
>>> Ah, that makes sense, fixed.
>>> 
>>>> On Jan 16, 2015, at 05:37, Robby Findler  
>>>> wrote:
>>>> 
>>>> One comment. The contract combinators are curried so that you can do
>>>> work on the partial applications. So don't write this:
>>>> 
>>>> (define ho-val-first-projection
>>>> impersonate/chaperone-async-channel) ctc) blame) val)
>>>> 
>>>> instead try to do some work earlier, when you first can. (The most
>>>> important thing is to minimize the work done after you get the 'val'
>>>> argument.)
>>>> 
>>>> Robby
>>> 
>> 
>> 
>> _
>>  Racket Developers list:
>>  http://lists.racket-lang.org/dev

_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] [racket] Implementing contracts for async channels

2015-01-19 Thread Alexis King
Any update on this? If there’s anything that still needs to be changed, let me 
know—otherwise, I’ll patiently wait for the process to run its course. Just 
checking in.

> On Jan 16, 2015, at 10:15, Alexis King  wrote:
> 
> Ah, that makes sense, fixed.
> 
>> On Jan 16, 2015, at 05:37, Robby Findler  wrote:
>> 
>> One comment. The contract combinators are curried so that you can do
>> work on the partial applications. So don't write this:
>> 
>> (define ho-val-first-projection
>> impersonate/chaperone-async-channel) ctc) blame) val)
>> 
>> instead try to do some work earlier, when you first can. (The most
>> important thing is to minimize the work done after you get the 'val'
>> argument.)
>> 
>> Robby
> 


_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] [racket] Implementing contracts for async channels

2015-01-16 Thread Alexis King
Ah, that makes sense, fixed.

> On Jan 16, 2015, at 05:37, Robby Findler  wrote:
> 
> One comment. The contract combinators are curried so that you can do
> work on the partial applications. So don't write this:
> 
> (define ho-val-first-projection
> impersonate/chaperone-async-channel) ctc) blame) val)
> 
> instead try to do some work earlier, when you first can. (The most
> important thing is to minimize the work done after you get the 'val'
> argument.)
> 
> Robby


_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] Implementing contracts for async channels

2015-01-15 Thread Alexis King
Sure thing, done. I’ve moved everything into racket/async-channel, added the 
missing functions, and added some tests. I squashed my commits into one, and 
the result is here:
https://github.com/lexi-lambda/racket/commit/0074ba13b712a87c9d05948ae075bcd74c7651e7
 
<https://github.com/lexi-lambda/racket/commit/0074ba13b712a87c9d05948ae075bcd74c7651e7>

Two simple points remain:

Where should the documentation go? Should it be under contracts or 
async-channels? I’d prefer the latter, but I’m not sure.
Since there is no impersonate-evt function, I don’t think my 
impersonate-async-channel function will actually work. Is that an accurate 
concern? How could I fix it?

Otherwise, I think this works fine and is probably ready to go.

> On Jan 15, 2015, at 15:09, Robby Findler  wrote:
> 
> I think they should probably all be exported from racket/async-channel.
> 
> Unless there is some reason to modify the internals of racket/contract
> to support them?
> 
> Robby
> 
> On Thu, Jan 15, 2015 at 4:50 PM, Alexis King  wrote:
>> Sorry, I wasn’t clear. The chaperone/impersonate-async-channel functions are 
>> exported from racket/async-channel. The async-channel contracts, however, 
>> are exported from racket/contract.
>> 
>>> On Jan 15, 2015, at 14:41, Robby Findler  
>>> wrote:
>>> 
>>> Just a small nit: why export that function from racket/contract and
>>> not an async-channel library?
>>> 
>>> Robby
>>> 
>>> 
>>> On Thu, Jan 15, 2015 at 3:33 PM, Alexis King  wrote:
>>>> As an update, I’ve made a bit more progress on this. I’ve implemented an
>>>> impersonate-async-channel function, and I’ve actually included this in the
>>>> exports from racket/contract. I also realized the blame information is
>>>> correct, it works fine. Most of the other issues remain, as well as a few
>>>> new questions:
>>>> 
>>>> There is no impersonate-evt function, so I’m not sure that my 
>>>> implementation
>>>> will work. What should I do about this?
>>>> I’d assume this needs to be documented/tested as well. Where should those
>>>> things be located?
>>>> 
>>>> 
>>>> On Jan 14, 2015, at 23:44, Alexis King  wrote:
>>>> 
>>>> Currently, async channels do not have contracts to check their contents.
>>>> This is a problem for Typed Racket, and it prevents typed code from
>>>> interacting with code that produces async channels.
>>>> 
>>>> I started looking into how to add contracts to the language, and it seems 
>>>> to
>>>> use the chaperones/impersonator system, as I suspected. However, async
>>>> channels obviously cannot be impersonated, so I needed to implement that as
>>>> well.
>>>> 
>>>> I modified the async-channel struct to use generics to allow it to be
>>>> impersonated or chaperoned, which I have exposed by implementing
>>>> chaperone-async-channel. I then tried implementing async-channel/c. The
>>>> internals of the contract system are a little beyond me, but I got a 
>>>> working
>>>> solution by following the example of the box contracts.
>>>> 
>>>> My work thus far can be found here:
>>>> https://github.com/lexi-lambda/racket/commit/84b9f3604891f3f2061fb28ed4800af8afa4751b
>>>> 
>>>> First of all, is this a correct approach? Have I done anything wrong, or
>>>> should I have done anything differently? I didn’t find much documentation 
>>>> on
>>>> the internals of either of these systems, so I mostly went about things as 
>>>> I
>>>> found them.
>>>> 
>>>> Second, obviously, not everything is implemented here. Among the additional
>>>> necessary changes are:
>>>> 
>>>> I need to implement support for impersonators and impersonator contracts
>>>> (right now I’ve only bothered to do chaperones).
>>>> I need to implement async-channel/c-first-order and
>>>> async-channel/c-stronger. I can probably figure out the latter, but I’m not
>>>> even sure what the former is supposed to do.
>>>> I need to implement a wrap-async-channel/c macro for the export. I’m not
>>>> sure how this works, either. From looking at wrap-box/c, it seems to add
>>>> some syntax properties, but I’m not sure what they do or how they work.
>>>> Somehow, the blame information has to be correct. Is that what the wrap
>>>> function does? Or do the async-channel functions need to be updated to
>>>> assign blame?
>>>> 
>>>> 
>>>> I’d really like to get this working, and I think I’m close, but I’m a 
>>>> little
>>>> inexperienced. I’d appreciate any help, even if it’s just pointing me in 
>>>> the
>>>> right direction.
>>>> 
>>>> Thanks!
>>>> 
>>>> 
>>>> 
>>>> _
>>>> Racket Developers list:
>>>> http://lists.racket-lang.org/dev
>>>> 
>> 

_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] Implementing contracts for async channels

2015-01-15 Thread Alexis King
Sorry, I wasn’t clear. The chaperone/impersonate-async-channel functions are 
exported from racket/async-channel. The async-channel contracts, however, are 
exported from racket/contract.

> On Jan 15, 2015, at 14:41, Robby Findler  wrote:
> 
> Just a small nit: why export that function from racket/contract and
> not an async-channel library?
> 
> Robby
> 
> 
> On Thu, Jan 15, 2015 at 3:33 PM, Alexis King  wrote:
>> As an update, I’ve made a bit more progress on this. I’ve implemented an
>> impersonate-async-channel function, and I’ve actually included this in the
>> exports from racket/contract. I also realized the blame information is
>> correct, it works fine. Most of the other issues remain, as well as a few
>> new questions:
>> 
>> There is no impersonate-evt function, so I’m not sure that my implementation
>> will work. What should I do about this?
>> I’d assume this needs to be documented/tested as well. Where should those
>> things be located?
>> 
>> 
>> On Jan 14, 2015, at 23:44, Alexis King  wrote:
>> 
>> Currently, async channels do not have contracts to check their contents.
>> This is a problem for Typed Racket, and it prevents typed code from
>> interacting with code that produces async channels.
>> 
>> I started looking into how to add contracts to the language, and it seems to
>> use the chaperones/impersonator system, as I suspected. However, async
>> channels obviously cannot be impersonated, so I needed to implement that as
>> well.
>> 
>> I modified the async-channel struct to use generics to allow it to be
>> impersonated or chaperoned, which I have exposed by implementing
>> chaperone-async-channel. I then tried implementing async-channel/c. The
>> internals of the contract system are a little beyond me, but I got a working
>> solution by following the example of the box contracts.
>> 
>> My work thus far can be found here:
>> https://github.com/lexi-lambda/racket/commit/84b9f3604891f3f2061fb28ed4800af8afa4751b
>> 
>> First of all, is this a correct approach? Have I done anything wrong, or
>> should I have done anything differently? I didn’t find much documentation on
>> the internals of either of these systems, so I mostly went about things as I
>> found them.
>> 
>> Second, obviously, not everything is implemented here. Among the additional
>> necessary changes are:
>> 
>> I need to implement support for impersonators and impersonator contracts
>> (right now I’ve only bothered to do chaperones).
>> I need to implement async-channel/c-first-order and
>> async-channel/c-stronger. I can probably figure out the latter, but I’m not
>> even sure what the former is supposed to do.
>> I need to implement a wrap-async-channel/c macro for the export. I’m not
>> sure how this works, either. From looking at wrap-box/c, it seems to add
>> some syntax properties, but I’m not sure what they do or how they work.
>> Somehow, the blame information has to be correct. Is that what the wrap
>> function does? Or do the async-channel functions need to be updated to
>> assign blame?
>> 
>> 
>> I’d really like to get this working, and I think I’m close, but I’m a little
>> inexperienced. I’d appreciate any help, even if it’s just pointing me in the
>> right direction.
>> 
>> Thanks!
>> 
>> 
>> 
>> _
>>  Racket Developers list:
>>  http://lists.racket-lang.org/dev
>> 


_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] Implementing contracts for async channels

2015-01-15 Thread Alexis King
As an update, I’ve made a bit more progress on this. I’ve implemented an 
impersonate-async-channel function, and I’ve actually included this in the 
exports from racket/contract. I also realized the blame information is correct, 
it works fine. Most of the other issues remain, as well as a few new questions:

There is no impersonate-evt function, so I’m not sure that my implementation 
will work. What should I do about this?
I’d assume this needs to be documented/tested as well. Where should those 
things be located?

> On Jan 14, 2015, at 23:44, Alexis King  wrote:
> 
> Currently, async channels do not have contracts to check their contents. This 
> is a problem for Typed Racket, and it prevents typed code from interacting 
> with code that produces async channels.
> 
> I started looking into how to add contracts to the language, and it seems to 
> use the chaperones/impersonator system, as I suspected. However, async 
> channels obviously cannot be impersonated, so I needed to implement that as 
> well.
> 
> I modified the async-channel struct to use generics to allow it to be 
> impersonated or chaperoned, which I have exposed by implementing 
> chaperone-async-channel. I then tried implementing async-channel/c. The 
> internals of the contract system are a little beyond me, but I got a working 
> solution by following the example of the box contracts.
> 
> My work thus far can be found here: 
> https://github.com/lexi-lambda/racket/commit/84b9f3604891f3f2061fb28ed4800af8afa4751b
>  
> <https://github.com/lexi-lambda/racket/commit/84b9f3604891f3f2061fb28ed4800af8afa4751b>
> 
> First of all, is this a correct approach? Have I done anything wrong, or 
> should I have done anything differently? I didn’t find much documentation on 
> the internals of either of these systems, so I mostly went about things as I 
> found them.
> 
> Second, obviously, not everything is implemented here. Among the additional 
> necessary changes are:
> 
> I need to implement support for impersonators and impersonator contracts 
> (right now I’ve only bothered to do chaperones).
> I need to implement async-channel/c-first-order and async-channel/c-stronger. 
> I can probably figure out the latter, but I’m not even sure what the former 
> is supposed to do.
> I need to implement a wrap-async-channel/c macro for the export. I’m not sure 
> how this works, either. From looking at wrap-box/c, it seems to add some 
> syntax properties, but I’m not sure what they do or how they work.
> Somehow, the blame information has to be correct. Is that what the wrap 
> function does? Or do the async-channel functions need to be updated to assign 
> blame?
> 
> I’d really like to get this working, and I think I’m close, but I’m a little 
> inexperienced. I’d appreciate any help, even if it’s just pointing me in the 
> right direction.
> 
> Thanks!

_
  Racket Developers list:
  http://lists.racket-lang.org/dev


[racket-dev] Implementing contracts for async channels

2015-01-14 Thread Alexis King
Currently, async channels do not have contracts to check their contents. This 
is a problem for Typed Racket, and it prevents typed code from interacting with 
code that produces async channels.

I started looking into how to add contracts to the language, and it seems to 
use the chaperones/impersonator system, as I suspected. However, async channels 
obviously cannot be impersonated, so I needed to implement that as well.

I modified the async-channel struct to use generics to allow it to be 
impersonated or chaperoned, which I have exposed by implementing 
chaperone-async-channel. I then tried implementing async-channel/c. The 
internals of the contract system are a little beyond me, but I got a working 
solution by following the example of the box contracts.

My work thus far can be found here: 
https://github.com/lexi-lambda/racket/commit/84b9f3604891f3f2061fb28ed4800af8afa4751b
 


First of all, is this a correct approach? Have I done anything wrong, or should 
I have done anything differently? I didn’t find much documentation on the 
internals of either of these systems, so I mostly went about things as I found 
them.

Second, obviously, not everything is implemented here. Among the additional 
necessary changes are:

I need to implement support for impersonators and impersonator contracts (right 
now I’ve only bothered to do chaperones).
I need to implement async-channel/c-first-order and async-channel/c-stronger. I 
can probably figure out the latter, but I’m not even sure what the former is 
supposed to do.
I need to implement a wrap-async-channel/c macro for the export. I’m not sure 
how this works, either. From looking at wrap-box/c, it seems to add some syntax 
properties, but I’m not sure what they do or how they work.
Somehow, the blame information has to be correct. Is that what the wrap 
function does? Or do the async-channel functions need to be updated to assign 
blame?

I’d really like to get this working, and I think I’m close, but I’m a little 
inexperienced. I’d appreciate any help, even if it’s just pointing me in the 
right direction.

Thanks!_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] Typed Racket does not play nice with submodules

2015-01-13 Thread Alexis King
After playing around with Asumu’s branch to use require again instead of 
local-require, submodules still don’t work. I’m not sure why, but I’ve 
collected a series of examples of how different things fail in different ways. 
Perhaps someone more intimately familiar with the internals of Typed Racket and 
Racket’s module system can help to figure something out from this information.

First, I have this simple program:

#lang typed/racket/base

(require (for-syntax racket/base
 syntax/parse
 typed-racket/private/syntax-properties))

(define-syntax (begin-ignored stx)
  (syntax-parse stx
[(_ ex:expr ...)
 (quasisyntax/loc stx
   #,(ignore #'(begin ex ...)))]))

(module foo racket
  (define x 7)
  (provide x))

(require 'foo)

(begin-ignored
  x)

This fails with the following error message:

link: module mismatch;
 possibly, bytecode file needs re-compile because dependencies changed
  importing module: 'explode
  exporting module: (submod "/tmp/explode.rkt" foo)
  exporting phase level: 0
  internal explanation: variable not provided (directly or indirectly) in: x

This is bizarre, and rather unhelpful. Note that this shouldn't involve any 
typechecking at all—using ignore should prevent that from happening—but somehow 
TR’s still making this fail. However, swapping typed/racket/base for 
typed/racket/base/no-check (perhaps unsurprisingly) makes it work fine.

Next up, I tried cheating a bit by using two submodules instead of just one. I 
hoped the following program would be a hacky workaround:

#lang typed/racket/base

(module foo racket/base
  (define x 7)
  (provide x))

(module bar typed/racket/base
  (require/typed
   (submod ".." foo)
   [x Number])
  (define y : Number x)
  (provide y))

(require 'bar)
y

Like the above, this program typechecks. However, it still fails with the exact 
same error message. Still, I was able to glean some more information from this 
oddity. Removing the final line of the program causes it to run successfully, 
as expected. Now, evaluating y in the REPL gives me a different error message:

Type Checker: missing type for identifier;
 consider using `require/typed' to import it
  identifier: y
  from module: (submod . bar) in: y

If anything, this feels even stranger. The provided variable is clearly typed, 
but apparently TR has decided it’s not. Why? I don’t know.

As a semi-interesting side note, simply changing the #lang declaration of the 
above program to racket/base makes it work without a hitch, demonstrating that 
the problem doesn’t seem to be within the require/typed form itself, but 
somehow has something to do with how TR handles the resulting binding?

Any ideas on what’s happening here? I’ve tried digging through some of the 
Typed Racket source, but I’m really too unfamiliar with how everything fits 
together to figure it out just yet.

Also, Asumu, a related problem: are there any issues with changing 
local-require back to require that would break anything else? Or can you 
possibly implement that change in TR with no issues?

> On Jan 12, 2015, at 08:06, Asumu Takikawa  <mailto:as...@ccs.neu.edu>> wrote:
> 
> On 2015-01-11 23:29:28 -0800, Alexis King wrote:
>>   This is a real problem, since Typed Racket’s require/typed form uses
>>   local-require, which in turn uses syntax-local-lift-require. This means
>>   that require/typed currently cannot require submodules.
> 
> Interesting, thanks for tracking this down! IIRC Typed Racket switched
> to using `local-require` in order to support uses of `require/typed` in
> the REPL/top-level.
> 
> (as the comment on
> https://github.com/racket/typed-racket/blob/master/typed-racket-lib/typed-racket/utils/require-contract.rkt#L57
>  
> <https://github.com/racket/typed-racket/blob/master/typed-racket-lib/typed-racket/utils/require-contract.rkt#L57>
> notes)
> 
> So one possible solution is to switch back to using `require` but also
> overhaul how TR handles the REPL to avoid these issues.
> 
> (for the REPL, local expanding everything at once doesn't work well
> because an early definition in a `begin` has to be registered
> before later clauses are typechecked)
> 
> Cheers,
> Asumu

_
  Racket Developers list:
  http://lists.racket-lang.org/dev


Re: [racket-dev] Typed Racket does not play nice with submodules

2015-01-13 Thread Alexis King
After playing around with Asumu’s branch to use require again instead of 
local-require, submodules still don’t work. I’m not sure why, but I’ve 
collected a series of examples of how different things fail in different ways. 
Perhaps someone more intimately familiar with the internals of Typed Racket and 
Racket’s module system can help to figure something out from this information.

First, I have this simple program:

#lang typed/racket/base

(require (for-syntax racket/base
 syntax/parse
 typed-racket/private/syntax-properties))

(define-syntax (begin-ignored stx)
  (syntax-parse stx
[(_ ex:expr ...)
 (quasisyntax/loc stx
   #,(ignore #'(begin ex ...)))]))

(module foo racket
  (define x 7)
  (provide x))

(require 'foo)

(begin-ignored
  x)

This fails with the following error message:

link: module mismatch;
 possibly, bytecode file needs re-compile because dependencies changed
  importing module: 'explode
  exporting module: (submod "/tmp/explode.rkt" foo)
  exporting phase level: 0
  internal explanation: variable not provided (directly or indirectly) in: x

This is bizarre, and rather unhelpful. Note that this shouldn't involve any 
typechecking at all—using ignore should prevent that from happening—but somehow 
TR’s still making this fail. However, swapping typed/racket/base for 
typed/racket/base/no-check (perhaps unsurprisingly) makes it work fine.

Next up, I tried cheating a bit by using two submodules instead of just one. I 
hoped the following program would be a hacky workaround:

#lang typed/racket/base

(module foo racket/base
  (define x 7)
  (provide x))

(module bar typed/racket/base
  (require/typed
   (submod ".." foo)
   [x Number])
  (define y : Number x)
  (provide y))

(require 'bar)
y

Like the above, this program typechecks. However, it still fails with the exact 
same error message. Still, I was able to glean some more information from this 
oddity. Removing the final line of the program causes it to run successfully, 
as expected. Now, evaluating y in the REPL gives me a different error message:

Type Checker: missing type for identifier;
 consider using `require/typed' to import it
  identifier: y
  from module: (submod . bar) in: y

If anything, this feels even stranger. The provided variable is clearly typed, 
but apparently TR has decided it’s not. Why? I don’t know.

As a semi-interesting side note, simply changing the #lang declaration of the 
above program to racket/base makes it work without a hitch, demonstrating that 
the problem doesn’t seem to be within the require/typed form itself, but 
somehow has something to do with how TR handles the resulting binding?

Any ideas on what’s happening here? I’ve tried digging through some of the 
Typed Racket source, but I’m really too unfamiliar with how everything fits 
together to figure it out just yet.

Also, Asumu, a related problem: are there any issues with changing 
local-require back to require that would break anything else? Or can you 
possibly implement that change in TR with no issues?

> On Jan 12, 2015, at 08:06, Asumu Takikawa  wrote:
> 
> On 2015-01-11 23:29:28 -0800, Alexis King wrote:
>>   This is a real problem, since Typed Racket’s require/typed form uses
>>   local-require, which in turn uses syntax-local-lift-require. This means
>>   that require/typed currently cannot require submodules.
> 
> Interesting, thanks for tracking this down! IIRC Typed Racket switched
> to using `local-require` in order to support uses of `require/typed` in
> the REPL/top-level.
> 
> (as the comment on
> https://github.com/racket/typed-racket/blob/master/typed-racket-lib/typed-racket/utils/require-contract.rkt#L57
> notes)
> 
> So one possible solution is to switch back to using `require` but also
> overhaul how TR handles the REPL to avoid these issues.
> 
> (for the REPL, local expanding everything at once doesn't work well
> because an early definition in a `begin` has to be registered
> before later clauses are typechecked)
> 
> Cheers,
> Asumu

_
  Racket Developers list:
  http://lists.racket-lang.org/dev


[racket-dev] syntax-local-lift-require is useless wrt submodules

2015-01-11 Thread Alexis King
I posted this to users@ first, but I think this might be more relevant here. 
The core problem is that syntax-local-lift-require 

 lifts the #%require form to the top of the enclosing module. This has the side 
effect of preventing those require specs from including submodules.

This is a real problem, since Typed Racket’s require/typed form uses 
local-require, which in turn uses syntax-local-lift-require. This means that 
require/typed currently cannot require submodules. It seems to me that either 
require/typed, require-local, or syntax-local-lift-require needs to be modified 
to be compatible with submodules, but I’m not sure how this should be achieved.

Should the module form be hoisted to the top of its enclosing module? Or will 
that cause problems I’m not foreseeing? I’d really appreciate some kind of 
solution to this problem because I’ve developed what I think is a fairly nice 
macro for use with Typed Racket, but I’d need it to properly interoperate with 
submodules to work correctly._
  Racket Developers list:
  http://lists.racket-lang.org/dev