| advertise add site services publishers database health videos | ![]() | about toolbar stats live show health store more stuff JOIN/LOGIN |
AHA - Hippotherapy/ Articles: Semantics americanhippotherapyassoc... | NEURO-SEMANTICS lcch.co.uk | Semantics hypnosisdirectory.net | data coding, knowledge bases,... hospitaliteurope.com |
In computer science, denotational semantics is an approach to formalizing the meanings of programming languages by constructing mathematical objects (called denotations) which describe the meanings of expressions from the languages. Other approaches to providing a formal semantics of programming languages include axiomatic semantics and operational semantics. Broadly speaking, denotational semantics is concerned with finding mathematical objects called domains that represent what programs do. For example, programs (or program phrases) might be represented by partial functions, or by Actor event diagram scenarios, or by games between the environment and the system: these are all general examples of domains. An important tenet of denotational semantics is that semantics should be compositional: the denotation of a program phrase should be built out of the denotations of its subphrases. [edit] Development of denotational semanticsDenotational semantics originated in the work of Christopher Strachey and Dana Scott in the 1960s. As originally developed by Strachey and Scott, denotational semantics provided the denotation (meaning) of a computer program as a function that mapped input into output.[1] To give denotations to recursively defined programs, Scott proposed working with continuous functions between domains, specifically complete partial orders. As described below, work has continued in investigating appropriate denotational semantics for aspects of programming languages such as sequentiality, concurrency, non-determinism and local state. Denotational semantics have been developed for modern programming languages that use capabilites like concurrency and exceptions, e.g., ActorScript[2], Concurrent ML[3], CSP[4], and Haskell[5]. The semantics of these languages is compositional in that the denotation of a phrase depends on the denotations of its subphrases. For example, the meaning of the applicative expression f(E1,E2) is defined in terms of semantics of its subphrases f, E1 and E2. In a modern programming language, E1 and E2 can be evaluated concurrently and the execution of one them might affect the other by interacting through shared objects causing their denotations to be defined in terms of each other. Also, E1 or E2 might throw an exception which could terminate the execution of the other one. The sections below describe special cases of the semantics of these modern programming languages. [edit] Denotations of recursive programsThe problem is as follows. We need to give a semantics to programs such as the definition of the factorial function as
The meaning of this factorial program should be a function on the natural numbers, but, because of its recursive definition, it is not clear how to understand this in a compositional way. In the semantics of recursion, a domain is typically a partial order, which can be understood as an order of definedness. For instance, the set of partial functions on the natural numbers can be given an order as follows:
The core idea behind using partial orders is that each recursive step broadens the domain on which a function is defined. Thus, for example, if f was the factorial function, recursively defined for only n iterations, then g could be the factorial function, recursively defined for n+1 (or more) iterations. It is usual to assume some properties of the domain, such as the existence of limits of chains (see cpo) and a bottom element. The partial order of partial functions has a bottom element, the totally undefined function. It also has least upper bounds of chains. Various additional properties are often reasonable and helpful: the article on domain theory has more details. One particularly important property is that of Scott continuity: one is interested in the continuous functions between domains (in the Scott topology). These are functions that preserve the order structure, and that preserve least upper bounds. In this setting, types are denoted by domains, and the elements of the domains roughly capturing the elements of the types. A denotational semantics is given to a program phrase with free variables in terms of a continuous function from the denotation of its environment type to the denotation of its type. For example, the phrase n*g(n-1) has type Nat, and it has two free variables: n, of type Nat, and g of type Nat -> Nat. Thus its denotation will be a continuous function
Under this order on the partial functions, the denotation of the factorial program can be given as follows. First, we must develop denotations (as Scott-continuous functions) for the basic constructions such as if-then-else, ==, and multiplication. One must also develop a denotational semantics for function abstraction and application. The program phrase
can then be given a denotation as a continuous function between the domains of partial functions
The denotation of the factorial program is defined to be the least fixed point of this function F. It is thus an element of the domain One way of proving the fixed point theorem gives an intuition as to why it is appropriate to give a semantics for recursion in this way. Every continuous function F:D→D on a domain D with bottom element ⊥ has a fixed point given by
Here, the notation Fi indicates i-many applications of F. The symbol "⊔" means "least upper bound". It is instructive to think of the components of the chain as "iterates". In the case of the factorial program above, we had a function F on the domain of partial functions.
Thus the least upper bound of this chain, then, is the full factorial function (which happens to be a total function). [edit] Denotational semantics of non-deterministic programsThe concept of power domains has been developed to give a denotational semantics to non-deterministic sequential programs. Writing P for a power domain constructor, the domain P(D) is the domain of non-deterministic computations of type denoted by D. There are difficulties with fairness and unboundedness in domain-theoretic models of non-determinism.[6] See Power domains for nondeterminism. [edit] Denotational semantics of concurrencyMany researchers have argued that the domain theoretic models given above do not suffice for the more general case of concurrent computation. For this reason various new models have been introduced. In the early 1980s, people began using the style of denotational semantics to give semantics for concurrent languages. Examples include Will Clinger's work with the actor model; Glynn Winskel's work with event structures and petri nets[7]; and the work by Francez, Hoare, Lehmann, and de Roever (1979) on trace semantics for CSP.[8] All these lines of enquiry remain under investigation (see e.g. Hewitt's Timed Diagrams Model,[9] or the various denotational models for CSP[4]). Recently, Winskel and others have proposed the category of profunctors as a domain theory for concurrency.[10][11] [edit] Denotational semantics of stateState (such as a heap) and simple imperative features can be straightforwardly modeled in the denotational semantics described above. All the textbooks below have the details. The key idea is to consider a command as a partial function on some domain of states. The denotation of "x:=3" is then the function that takes a state to the state with 3 assigned to x. The sequencing operator ";" is denoted by composition of functions. Fixed-point constructions are then used to give a semantics to looping constructs, such as "while". Things become more difficult in modelling programs with local variables. One approach is to no longer work with domains, but instead to interpret types as functors from some category of worlds to a category of domains. Programs are then denoted by natural continuous functions between these functors.[12][13] [edit] Denotations of data typesMany programming languages allow users to define recursive data types. For example, the type of lists of numbers can be specified by
This section deals only with functional data structures that cannot change. Conventional programming languages would typically allow the elements of such a recursive list to be changed. For another example: the type of denotations of the untyped lambda calculus is
The problem of solving domain equations is concerned with finding domains that model these kinds of datatypes. One approach, roughly speaking, is to consider the collection of all domains as a domain itself, and then solve the recursive definition there. The textbooks below give more details. Polymorphic data types are data types that are defined with a parameter. For example, the type of α lists is defined by
Lists of numbers, then, are of type Nat list, while lists of strings are of String list. Some researchers have developed domain theoretic models of polymorphism. Other researchers have also modeled parametric polymorphism within constructive set theories. Details are found in the textbooks listed below. A recent research area has involved denotational semantics for object and class based programming languages.[14] [edit] Denotational semantics for programs of restricted complexityFollowing the development of programming languages based on linear logic, denotational semantics have been given to languages for linear usage (see e.g. proof nets, coherence spaces) and also polynomial time complexity[15]. [edit] Denotational semantics of sequentialityThe problem of full abstraction (see below) for the sequential programming language PCF was, for a long time, a big open question in denotational semantics. The difficulty with PCF is that it is a very sequential language. For example, there is no way to define the parallel-or function in PCF. It is for this reason that the approach using domains, as introduced above, yields a denotational semantics that is not fully abstract. This open question was mostly resolved in the 1990s with the development of game semantics and also with techniques involving logical relations.[16] For more details, see the page on PCF. [edit] Denotational semantics as source-to-source translationIt is often useful to translate one programming language into another. For example, a concurrent programming language might be translated into a process calculus; a high-level programming language might be translated into byte-code. (Indeed, conventional denotational semantics can be seen as the interpretation of programming languages into the internal language of the category of domains.) In this context, notions from denotational semantics, such as full abstraction, help to satisfy security concerns.[17][18] [edit] AbstractionIt is often considered important to connect denotational semantics with operational semantics. This is especially important when the denotational semantics is rather mathematical and abstract, and the operational semantics is more concrete or closer to the computational intuitions. The following properties of a denotational semantics are often of interest.
Additional desirable properties we may wish to hold between operational and denotational semantics are:
[edit] CompositionalityAn important aspect of denotational semantics of programming languages is compositionality, by which the denotation of a program is constructed from denotations of its parts. For example consider the expression "7 + 4". Compositionality in this case is to provide a meaning for "7 + 4" in terms of the meanings of "7", "4" and "+". A basic denotational semantics in domain theory is compositional because it is given as follows. We start by considering program fragments, i.e. programs with free variables. A typing context assigns a type to each free variable. For instance, in the expression (x + y) might be considered in a typing context (x:nat,y:nat). We now give a denotational semantics to program fragments, using the following scheme.
Now, the meaning of the compound expression (7+4) is determined by composing the three functions 〚⊢7:nat〛:1→ℕ⊥, 〚⊢4:nat〛:1→ℕ⊥, and 〚x:nat,y:nat⊢x+y:nat〛:ℕ⊥×ℕ⊥→ℕ⊥. In fact, this is a general scheme for compositional denotational semantics. There is nothing specific about domains and continuous functions here. One can work with a different category instead. For example, in game semantics, the category of games has games as objects and strategies as morphisms: we can interpret types as games, and programs as strategies. For a simple language without recursion, we can make do with the category of sets and functions. For a language with side-effects, we can work in the Kleisli category for a monad. For a language with state, we can work in a functor category. Milner has advocated modelling location and interaction by working in a category with interfaces as objects and bigraphs as morphisms [20] [edit] Semantics versus implementationAccording to Dana Scott [1980]:
According to Clinger [1981]:
[edit] Connections to other areas of computer scienceSome work in denotational semantics has interpreted types as domains in the sense of domain theory which can be seen as a branch of model theory, leading to connections with type theory and category theory. Within computer science, there are connections with abstract interpretation, program verification, and model checking. Monads were introduced to denotational semantics as a way of organising semantics, and these ideas have had a big impact in functional programming (see monads in functional programming). [edit] References
[edit] Further reading[edit] Textbooks
[edit] Other references
[edit] External links
|
| ↑ top of page ↑ | about thumbshots |