Has anyone used Datalog or RDF as a basis beyond model-driven development, like projectional editing or unikernel generation?
By the way, no this is not a "homework question". Yes, I did research it. I think some people on here can probably point me to some interesting links that weren't obvious on Google.
Has anyone used Datalog or RDF as a basis for something beyond basic model-driven development, like projectional editing or unikernel generation?
Seems like Google is hitting on some model-driven development stuff that uses RDF, but what I really am interested in is generating the whole program or even system entirely based on some kind of semantic model, not just representing some domain model with it.
Unikernels: Rise of the Virtual Library Operating System -- this is what is making me wonder about this type of thing again. I think having a high-level description of all layers of the whole system makes sense, but not everyone is going to want to use OCaml, and practically speaking you will probably want to be able to generate program code or at least configuration files for specific languages or existing machines/VMs or interpreters.
The idea is to have kind of RDF schema or semantic model or common datalog database of facts and rules and then use that as a basis for modeling a program or entire system and then generating the program code from that.
Or better have different programming languages defined using this common set of rules and facts, so the programming language code can be automatically translated back into the common representation and then processed using another tool or edited using a particular interactive projection.
The basic idea is that assuming the whole system is open source, all of the different programming languages or database formats or programs or data representations are defined based on some common semantics in a logic format like datalog. This should make it much easier for different systems (like programming languages or databases or applications) to work together.
I am wondering especially if someone has applied an approach like that to projectional editing or unikernel generation or maybe both together.
My proximal question is: how can I structure an exception-free parser to conveniently handle syntax errors? My more global question is: how do people do that in an idiomatically functional way?
Just about every line of parser code can (transitively) result in a syntax error. For example, to parse the language construct "split x into y" I write (roughly):
acceptToken(split) // Could fail if split is misspelled source = expression() // Could fail if expression is faulty or missing acceptToken(into) // Could fail dest = expression() // Could fail acceptToken(newline) // Could fail return new JoinNode(source, dest)
It is convenient to expect that any of these calls will throw an exception, in particular that lines subsequent to the failure will not execute. Repeated wrapping and testing each line is just the sort of thing exceptions are supposed to save us from. (Although I agree the details of handling exceptions — rolling back the program state — are almost impossible to get right.)
What I am looking for is a design architecture that will let me continue exploit the isomorphism between the grammar and the code structure: one term in the grammar maps to one line of parser code. Not one line of parser code, wrapped in conditional tests, with each line testing the success/failure of its predecessor.
There have been some suggestions in this thread:
that involve optional types and comparisons to languages like Rust and Scala, but I did not see usable ideas from actual compiler writers. Suggestions or pointers/references welcome.
I've sketched some ideas about slot-based interfaces as a way to turn method names into first-class citizens of the language, with an example of the resulting framework as applied to C++:
The key idea is to treat objects as polymorphic functors and regard a method call like
as an invocation of
If we now define a slot as a generalized functor accepting objects as their first parameter and with the following semantics:
foo(x,arg1,...,argn) --> x(foo,arg1,...,argn)
then objects and slots become dual notions, and many interesting patterns arise around method decoration, smart references, etc.
I wonder if these ideas have been already explored in a more general setting than the toy framework described here.
Blog post by Olin Shivers.
Excerpts with my editorial:
The treatment bothers me, because it doesn't distinguish very well between names for computers and names for people, which contrasts in the idealism I picked up from Edwards ("names are too valuable to be wasted on compilers"):
And afterwards, dives into the computational:
He then visits the humanistic viewpoint:
Queue a bunch of suspiciously OO names that take the form verb-noun or noun-verb. And then finally back to the computational viewpoint, where FP reigns supreme:
I'm of the opinion that the humanistic and computational nature of names are completely different, and find it weird that they are presented in such close quarters as to imply a strong connection between them.
Also, the way FP and OOP deal with names illuminates a lot about the paradigms. In OOP, objects have identities (intrinsic globally unique names that allow for easy aliasing) with interfaces that are named according to natural metaphors; FP is rather more oriented to symbolic reasoning where values (in pure FP at least) are anonymous and defined strictly by their structure, functions are named according to transformations on this data (map, reduce, select, etc...).
We are having another PLATEAU workshop at SPLASH 2014. We have a new category for "Hypotheses Papers" and thought this would be particularly appealing to the LTU community.
Programming languages exist to enable programmers to develop software effectively. But how efficiently programmers can write software depends on the usability of the languages and tools that they develop with. The aim of this workshop is to discuss methods, metrics and techniques for evaluating the usability of languages and language tools. The supposed benefits of such languages and tools cover a large space, including making programs easier to read, write, and maintain; allowing programmers to write more flexible and powerful programs; and restricting programs to make them more safe and secure.
PLATEAU gathers the intersection of researchers in the programming language, programming tool, and human-computer interaction communities to share their research and discuss the future of evaluation and usability of programming languages and tools.
Some particular areas of interest are:
PLATEAU encourages submissions of three types of papers:
Research and position papers: We encourage papers that describe work-in-progress or recently completed work based on the themes and goals of the workshop or related topics, report on experiences gained, question accepted wisdom, raise challenging open problems, or propose speculative new approaches. We will accept two types of papers: research papers up to 8 pages in length; and position papers up to 2 pages in length.
Hypotheses papers: Hypotheses papers explicitly identify beliefs of the research community or software industry about how a programming language, programming language feature, or programming language tool affects programming practice. Hypotheses can be collected from mailing lists, blog posts, paper introductions, developer forums, or interviews. Papers should clearly document the source(s) of each hypothesis and discuss the importance, use, and relevance of the hypotheses on research or practice. Papers may also, but are not required to, review evidence for or against the hypotheses identified. Hypotheses papers can be up to 4 pages in length.
Papers will be published in the ACM Digital Library at the authors’ discretion.
Workshop paper submission due - 1 August, 2014
Josh Bloch, former Chief Java Architect at Google and Distinguished Engineer at Sun Microsystems.
I have been working on an interpreter for a mini-subset of Prolog as I find it interesting how logic languages hold a central place in proof-assistants, theorem-provers and type-systems.
What I am interested in is a minimal and sound dialect of prolog to server as a starting point for further investigation. There are obviously several design points to discuss, but negation appears to be the most fundamental. Obviously as I am interested in soundness I want to operate in a Herbrand universe, which means unification with an occurs check.
The problem with negation seems to stem from the Prolog programming model. It appears to me that at some point "failure/unsat" and "falseness" (and "success/sat" and "truthfulness") have become confused with each other. This leads to negation as failure, the unsoundness of which is easily shown:
:- not (not (X = 0)), not (not (X = 1)). yes.
Various solutions to this have been proposed, three-valued (Kleene) logic, four valued (Belnap) logic, negation as inconsistency, negation as refutation etc. All of those complicate the resolution process, but do solve the problem. Strong negation seems interesting because it is local and not fragile like some of these methods. I particularly liked the combination of a four-valued logic (because the bilattice structure is nice) and strong negation, and started to look at implementing it.
What interested me is that the logic values are seen as success values, so that a functor can be 'true' or 'false' without failing. In which case, why make them special 'values' in the language at all, surely they can be treated as normal atoms? Taking list membership as an example, we might want to define:
member(Key, cons(def(Key, _), _), true). member(Key, nil, false). member(Key, cons(_, Tail), X) :- member(Key, Tail, X).
We can even define 'not' as a predicate (fail if arg is true):
not(false). not_member(Key, List) :- member(Key, List, X), not(X).
or a binary operator
not(true, false). not(false, true). not_member(Key, List, X) :- member(Key, List, Y), not(Y, X).
Without any of the logical unsoundness of negation as failure. There is obviously a parallel with dependent type systems (curry-howard), which I don't think have negation.
I have put the source code for my simple logic language "Clors" on GitHub https://github.com/keean/Clors. Its a still experimental, and is suffering form many changes and false starts, so needs a little tidying up (I have just removed meta-interpreters because they turn out to be unsound), and needs updating to use my parser combinator library.
So the question is, do logic languages need builtin negation?
Mindless Coding, uses Coq to emit Ocaml:
'Mindless' if you are smart enough to be able to do incremental steps in proof-making :-)
Does anyone know of any work where HM-style type inference is performed at run-time rather than compile time? By this, I mean unification with type variables dynamically using precise (run-time) types.
(This is about semantics in a programming language for creation of responders.) I've been thinking about something off and on recently, and I wonder what the name of this idea is within the context of PL (programming language) terminology, if there is a standard name. If there's not a conventional name, I wonder if it resembles anything else. Also, if the idea itself seems incoherent, or inferior to a better way of looking at it, I'd like to hear that too.
When we write code to pragmatically do something, it calls an interface that already exists, that is already established, which is ready to respond to such invocation. At a given moment in time, some number of callable functions exist in a current process, as well as executable programs in an operating system context, and reachable servers over comm systems (of which networking is a subset). Tools at hand willing to respond to new uses thus offer affordances for latent services that can be invoked. System design includes arranging affordances you need for an app will exist at runtime, and bringing up a complex system — when it starts — typically involves carefully ordered initialization so components are ready before actual first use, or can lazily wait until a service is ready.
The idea I'm thinking of is related to boot-strapping, but that idea often refers to traversing a well-known path known statically ahead of time: getting from start at A to everything ready to go at B, where A and B are pretty much the same most of the time. I'm interested in how one plans a programming language or app framework (etc) so the concept is explicitly addressed by the tools, so there's a way to talk about designing points A and B in time, within a programming language for example. It's related to both compile-time build processes as well as runtime data structure creation necessary when a program starts before some operations can be supported. If servers and other actors are launched and wait to handle messages and connections, it's also about language used to describe timing, types, and semantics of such behavior.
If you write an app with a virtual file system, a configuration phase that mounts resources where they can be found by clients later is also under the same semantic umbrella. Managing namespaces in general, and actually creating bindings at runtime are also semantically related. So module systems in a programming language touch part the same topic, if the element of time is explicitly handled. Managing dynamic evolution of binding systems in time is the part I want a sub-lexicon of terminology to address, rather than devs merely assuming an implicit common understanding no one ever talks about. (It's hard to bring language tools to bear on things never encoded.)
I know Erlang has conventions for managing restart of processes that fail, and that sort of thing. Is there a larger practice outside Erlang that gives names to elements of service management? Best would be terminology that is applicable at all times during programming execution, and not just launch, so it's easy to talk about stopping and restarting embedded sub-systems without terminating host operating system processes, with jargon re-usable outside just one framework. Every time you think of another word that gets used to describe part of such processes, I might find it useful, so even short posts mentioning specific words is helpful.
My point in posting here? It seems reasonable for a programming language to be able to write specifications for time dependent behavior of bindings visible when starting and stopping visibility of callable entities with dependencies on one another. I suppose I could re-purpose terminology used for a narrow context for use in a more general way, but that easily confuses people.
As I promissed to natecull, here is a 7 pages Synth specification overview: document
It explains its basic state machine functionality and brings a neat integration of reactive programming. All critics are welcome, as it is still at development stage and it can be changed until its release time.
Active forum topics
New forum topics