I'm debating trying to use something like define-datatype, as used in EOPL and PLAI (and available in the Racket languages that support those books) early in my first-year undergraduate class. (Opinions on the wisdom of this, or on my sanity in general, by direct e-mail, please.)
In a teaching-language program, just using `require' to include define-datatype and type-case or 'cases' from plai/datatype.rkt or eopl/datatype.rkt appears to work so long as the teaching language is ISL or higher. In BSL or BSL+, I seem to be running into a thicket of rules designed to protect students. I'm using as my exploratory example the trivial arithmetic expression evaluator from the beginning of PLAI (2007 edition). Using plai/datatype.rkt generates an error because a use of define-datatype involves function names in expression positions (as contracts for field names). If I wrap these in applications of first-order->higher-order from lang/prim, which seems to be designed for this task, I get an error the first time I try to use a variant constructor (in the PLAI example, in 'parse'). The constructors seem to be defined, but also seem to be regarded as variables instead of functions. This is also what happens with eopl/datatype.rkt (the other error does not seem to arise).
Do I have a hope of pulling this off, and if so, how? Many thanks. --PR
____________________
Racket Users list:
http://lists.racket-lang.org/users
> I'm debating trying to use something like define-datatype, as used in > EOPL and PLAI (and available in the Racket languages that support those > books) early in my first-year undergraduate class. (Opinions on the > wisdom of this, or on my sanity in general, by direct e-mail, please.)
> In a teaching-language program, just using `require' to include > define-datatype and type-case or 'cases' from plai/datatype.rkt or > eopl/datatype.rkt appears to work so long as the teaching language is > ISL or higher. In BSL or BSL+, I seem to be running into a thicket of > rules designed to protect students. I'm using as my exploratory example > the trivial arithmetic expression evaluator from the beginning of PLAI > (2007 edition). Using plai/datatype.rkt generates an error because a use > of define-datatype involves function names in expression positions (as > contracts for field names). If I wrap these in applications of > first-order->higher-order from lang/prim, which seems to be designed for > this task, I get an error the first time I try to use a variant > constructor (in the PLAI example, in 'parse'). The constructors seem to > be defined, but also seem to be regarded as variables instead of > functions. This is also what happens with eopl/datatype.rkt (the other > error does not seem to arise).
> Do I have a hope of pulling this off, and if so, how? Many thanks. --PR
Here's a first cut at a module that you can import into BSL programs.
The least obvious part is defining a new `define-type' and `type-case'
that invents hidden names for the variants and them maps between them
while expanding to the original forms.
> Here's a first cut at a module that you can import into BSL programs.
> The least obvious part is defining a new `define-type' and `type-case'
> that invents hidden names for the variants and them maps between them
> while expanding to the original forms.
Wow, thanks. I will study the code and do my best to understand it, and test it for deployment next fall. I can already see the outline of how your code achieves what you describe, but could you please say a few words about why that's necessary, to improve my understanding of BSL? Thanks again. --PR
____________________
Racket Users list:
http://lists.racket-lang.org/users
At Mon, 05 Nov 2012 08:13:16 -0500, Prabhakar Ragde wrote:
> On 2012-11-05 6:43 AM, Matthew Flatt wrote:
> > Here's a first cut at a module that you can import into BSL programs.
> > The least obvious part is defining a new `define-type' and `type-case'
> > that invents hidden names for the variants and them maps between them
> > while expanding to the original forms.
> Wow, thanks. I will study the code and do my best to understand it, and > test it for deployment next fall. I can already see the outline of how > your code achieves what you describe, but could you please say a few > words about why that's necessary, to improve my understanding of BSL? > Thanks again. --PR
You had worked out the need for `first-order->higher-order' on
contracts for variant fields. The flip side is using BSL's `define' to
define variant constructors so that BSL is willing to see them used in
an application position.
But if the constructors are defined with BSL's `define', then you have
to give different names to the variants as defined by `define-type', so
those can be wrapped by BSL-friendly definitions. The last piece, then,
is to rewrite variant names in a `type-case' (which correspond to the
BSL-`define'd wrappers) to the names as defined by `define-type'.
BSL uses special syntax information (installed by beginner:define) to only
allow applications on first-order functions. For example,
(define (f a)
(a 1))
is an error in BSL. The way this is detected is that every top-level define
(like for 'f') has a special notation on it that says "I'm a function".
Since 'a' doesn't have this, then the macro for app in BSL can throw an
error.
The main thing that this macro does is give that information to the
identifiers, but you need to redefine them, which causes the need for the
variant mapping since type-case is looking for the original variant names.
Jay
On Mon, Nov 5, 2012 at 6:13 AM, Prabhakar Ragde <plra...@uwaterloo.ca>wrote:
> Here's a first cut at a module that you can import into BSL programs.
>> The least obvious part is defining a new `define-type' and `type-case'
>> that invents hidden names for the variants and them maps between them
>> while expanding to the original forms.
> Wow, thanks. I will study the code and do my best to understand it, and
> test it for deployment next fall. I can already see the outline of how your
> code achieves what you describe, but could you please say a few words about
> why that's necessary, to improve my understanding of BSL? Thanks again. --PR
On Mon, Nov 5, 2012 at 7:22 AM, Jay McCarthy <jay.mccar...@gmail.com> wrote:
> every top-level define (like for 'f') has a special notation on it that
> says "I'm a function". Since 'a' doesn't have this, then the macro for app
> in BSL can throw an error.
I think they are macro bindings that are actually structures with
prop:procedure functions, so that the app macro (like 'special') below, can
check where they came from.
#lang racket
(struct example (f x)
#:property
prop:procedure
(λ (e y)
((example-f e) (example-x e) y)))
On Mon, Nov 5, 2012 at 6:49 AM, Grant Rettke <gret...@acm.org> wrote:
> On Mon, Nov 5, 2012 at 7:22 AM, Jay McCarthy <jay.mccar...@gmail.com>wrote:
>> every top-level define (like for 'f') has a special notation on it that
>> says "I'm a function". Since 'a' doesn't have this, then the macro for app
>> in BSL can throw an error.
> What Racket language feature is used to do that?