I understand 'user modeling' [1] to broadly address long-term details (e.g.
user preferences and settings), mid-term details (goals, tasks, workflow),
and short-term details (focus, attention, clipboards and cursors,
conversational context, history). The unifying principle is that we have
more context to make smart decisions, to make systems behave in ways their
users expect. This is a form of context sensitivity, where the user is
explicitly part of the context.

Programming can be understood as a form of user interface. But,
historically, user modeling (in this case 'programmer modeling') has been
kept carefully separate from the program itself; instead, it is instead
part of an Integrated Development Environment (IDE)

*Hypothesis:* the separation of user-model from program has hindered both
programmers and the art of programming. There are several reasons for this:

1) Our IDEs are not sufficiently smart. The context IDEs keep is heuristic,
fragile, and can be trusted with only the simplest of tasks.
2) Poor integration with the IDE and visual environments: it is difficult
to assign formal meaning to gestures and programmer actions.
3) Programmer-layer goals, tasks, and workflows are generally opaque to the
IDE, the programs and the type system.
4) Our code must be explicit and verbose about many interactions that could
be implicit if we tracked user context.
5) Programmers cannot easily adjust their environment or language to know
what they mean, and act as they expect.

I believe we can do much better. I'll next provide a little background
about how this belief came to be, then what I'm envisioning.

*Background*

Recently, I started developing a tacit representation for an arrowized
reactive programming model. Arrows provide a relatively rigid 'structure'
to the program. In the tacit representation, this structure was represented
as a stack consisting of a mix of compile-time values (text, numbers,
blocks) and runtime signals (e.g. mouse position). Essentially, I can give
the stack a 'static type', but I still used FORTH-like idioms to "roll" and
"pick" items from the stack as though it were a dynamic structure. With
just a little static introspection, I could even model `7 pick` as copying
the seventh element of the stack to the top of the stack.

But I didn't like this single stack environment. It felt cramped.

Often, I desire to decompose a problem into multiple concurrent tasks or
workflows. And when I do so, I must occasionally integrate intermediate
results, which can involve some complex scattering and gathering
operations. On a single stack, this integration is terribly painful: it
involves rolling or copying intermediate signals and values upwards or
downwards, with relative positions that are difficult to remember.
Conclusion: a single stack is good only for a single, sequential task - a
single pipeline, in a dataflow model.

But then I realized: I'm not limited to modeling a stack. A stack is just
one possible way of organizing and conceptualizing the 'type' of the arrow.
I can model any environment I please! (I'm being serious. With the same
level of introspection needed for `7 pick`, I could model a MUD, MOO, or
interactive fiction in the type system.) After experimenting with tree
zippers [2] or a list of anonymous stacks [3], I'm kind of (hopefully)
settling on an easy-to-use environment [4] that consists of:

* current stack
* hand
* current stack name
* list of named stacks

The current stack serves the traditional role. The 'hand' enables
developers to 'take' and 'put' objects (and juggle a few of them, like
'roll' except for the hand) - it's really convenient even for operating on
a single stack, and also helps carry items between stacks (implicit data
plumbing). The list of named stacks is achieved using compile-time
introspection (~type matching for different stack names) and is very
flexible:

* different stacks for different tasks; ability to navigate to a different
stack (goto)
* programmers can 'load' and 'store' from a stack remotely (treat it like a
variable or register)
* programmers can use named stacks to record preferences and configuration
options
* programmers can use named stacks to store dynamic libraries of code (as
blocks)

As I developed this rich environment, it occurred to me that I had
essentially integrated a user-model with the program itself. Actually, my
first thought was closer to "hey, I'm modeling a character in a game! Go go
Data Plumber!" The programmer is manipulating an avatar, navigating from
task to task and stack to stack. The programmer has items in hand, plus a
potential inventory (e.g. an "inventory" stack). To push metaphors a bit: I
can model keyrings full of sealer/unsealer pairs, locked rooms with sealed
values, unique 'artifacts' and 'puzzles' in the form of affine and relevant
types [5], quests goals in the form of  fractional types (representing
futures/promises) [6], and 'spellbooks' in the form of static capabilities
[7]. But in retrospect, the relationship to user modeling seems obvious,
and I can put all this more boring terms of modeling goals, tasks,
requirements, workflows, user extensions and preferences, etc..

All the normal abstraction principles apply, and developers will quickly
build higher-level procedures for higher-level thinking, and build
libraries of reusable abstractions. An arrowized model also supports
'partial application' (the `first` primitive) so we can precisely control
how much of this context is made available to a subprogram.

In the type system, the current stack, hand, stack name, and list of named
stacks is represented as a simple anonymous product type:

        (cs * (h * (csn * lns)))

Every non-trivial action the programmer performs will manipulate the deeper
'type' of this environment. I.e. it's extremely heterogeneous, and very
mutable (albeit in a "pure functional" way, from an outside perspective).
The environment type is complicated and mutable; short term I'll be okay,
but long term I expect I'll need something to aide my memory. Fortunately,
the IDE can help.

*Vision*
*
*
An IDE can *render* the types in the environment, dedicating more space and
detail to the types near me. Usefully, I can even animate progressions,
easily show the environment reaches a particular state - or basically a
replay of the programmer actions. With a few idioms (e.g. a "how-to-render"
stack, or integration primitives), developers could provide a great deal of
control over how things are rendered.

IDE integration can also cover interaction.

When users focus on a stack in the IDE, it corresponds to navigation code
being added to the program. When a user selects an object, the appropriate
code is injected to copy or take it. When a user opens a menu, the
available options correspond to macros that will be literally added to the
program. (Also, a menu might be extensible from within the program based on
the contents of an "ext-menu" stack.) Undo would be trivially integrated
and would have real meaning.

It isn't a big step from here, to programming with a gamepad, or in an
AR/VR environment. (Nor are we a big step from building an interactive
fiction in the type system. :)

An IDE could still help developers in the traditional ways: provide
context-sensitive suggestions based on the current 'type' of the
environment, provide 'cleaning' operations that reorganize the contents of
a stack and eliminate unnecessary copies, provide 'refactoring' support
that analyze block-constructor code for similarities, etc.. In addition, an
IDE could be rewriting the history, optimizing it - e.g. eliminating
unnecessary navigation or sequential `take put` operations. (This isn't
strictly necessary; pure data plumbing can be trivially optimized away at
compile-time. However a faster compile-time is also nice.) Rewrites could
also be the basis for building gesture macros. Of course, the model I
developed was meant primarily for signal manipulation - e.g. a signal might
be "mouse position". I think I'd mostly be operating at another layer of
indirection, for an IDE - where the 'signals' contain static building
blocks of code that will manipulate signals on my behalf.

Use of a programmer model within the program is a powerful, uniform basis
for rich, extensible development environments that can eventually subsume
other UI models. Essentially, all user-interaction is subsumed as
programming, all GUIs are modeled as types, and with a decent type system
this can be powerful indeed.

(Note: I suspect that multi-programmer environments are also feasible, i.e.
with multiple programmer models.  However, I would tend to model multiple
programmers as each having their own environment within a larger system,
through which they can share some capabilities or libraries.)

Best,

Dave

[1] http://en.wikipedia.org/wiki/User_modeling
[2]
http://awelonblue.wordpress.com/2013/08/12/tacit-programming-with-arrows-hands-and-zippers/

[3]
http://awelonblue.wordpress.com/2013/08/14/multi-stack-environment-in-awelon/
[4]
http://awelonblue.wordpress.com/2013/08/26/multi-stack-environment-part-2/
[5] http://en.wikipedia.org/wiki/Substructural_type_system
[6]
http://awelonblue.wordpress.com/2013/08/24/pipes-that-flow-in-both-directions/
[7] http://en.wikipedia.org/wiki/Capability-based_security
_______________________________________________
fonc mailing list
fonc@vpri.org
http://vpri.org/mailman/listinfo/fonc

Reply via email to