Opting for oracles: Difference between revisions

From HaskellWiki
mNo edit summary
(Content extensively rewritten)
Line 1: Line 1:
== What an oracle is ==
It was the work of Emil Post and others that established the oracle more formally:
<blockquote>
<blockquote>
LML had a fully fledged implementation of oracles running of a multi-processor (a Sequent Symmetry) back in ca 1989. The description in [https://web.archive.org/web/20221015141447/https://cth.altocumulus.org/~hallgren/Thesis/fudgets_thesis_color.pdf the Fudgets thesis] refers to this implementation. It was fairly pleasant to work with and quite practical.
Now suppose instead, says Turing
[https://pure.mpg.de/rest/items/item_2403325_2/component/file_2403324/content <span><span>]&nbsp;
in effect, this situation obtains with the following
modification. That at certain times the otherwise machine determined
process raises the question is a certain positive integer in a given
recursively enumerable set <i>S</i><sub>2</sub> of positive integers, and that the machine
is so constructed that were the correct answer to this question supplied
on every occasion that arises, the process would automatically
continue to its eventual correct conclusion.<sup>23</sup>
 
<sup>23</sup>Turing picturesquely suggests access to an “oracle” which would supply the
correct answer in each case. The “if” of mathematics is however more conducive to the
development of a theory.


:<small>[http://lambda-the-ultimate.org/node/1665#comment-2033 Lennart Augustsson.]</small>
:<small>[https://www.ams.org/journals/bull/1944-50-05/S0002-9904-1944-08111-1/S0002-9904-1944-08111-1.pdf Recursively enumerable sets of positive integers and their decision problems] (page 311).</small>
</blockquote>
</blockquote>


__TOC__
Of interest here is the phrase <q>the otherwise machine determined process</q> -
what answers the question is separate from that process. This implies:
 
* an oracle cannot be computable.
 
::If it was, it could also be computed by the machine-determined process.


== Oracles, defined ==
* an oracle doesn't access the internal state of the machine that calls it.


An ''oracle'' is a value that can be viewed as having the ability to predict what another value will be. The predicted value is usually the result of a computation involving information which cannot be represented as regular values by the language defining the computation. The oracle, by seeming to contain the prediction, limits the effect on the semantics of the language being used.
::It only needs the positive integer of interest to supply the required answer, with all other actions being the responsibility of the machine-determined process.


This makes the use of oracles highly relevant to languages intended to preserve referential transparency, such as Haskell.
* an oracle returns a boolean result.


== Oracles in use ==
::There are only two definite answers to the question:
:::<q>is a certain positive integer in a given recursively enumerable set <i>S</i><sub>2</sub> of positive integers</q>
::and they can be mapped to the boolean values <code>True</code> and <code>False</code>.


The early use of oracles in programming languages focused on coping with the <span class="plainlinks">[https://wiki.haskell.org/Category:Nondeterminism nondeterminism]<span> <!-- [[Category:Nondeterminism|nondeterminism]] --> arising from the occurrence of events outside the language - one classic example being ''concurrency''. For a language to support it, it must provide computations some means of allowing multiple sub-computations to each progress at their own rate, depending on the current availability of suitable resources, which can either be:
Hence the oracle is a noncomputable function - originally a predicate, but
now more commonly a function returning a wider range of values. This makes
the use of oracles highly relevant to languages intended to preserve
referential transparency, such as Haskell.


* ''inside'' the language e.g. definitions which the computations share, or
== An adapted example ==


* ''outside'' of it e.g. hardware devices for storage, audiovisual or networking.
Based on page 42 of 76 in [http://www.people.cs.uchicago.edu/~soare/Turing/shagrir.pdf Turing-Post Relativized Computability and Interactive Computing]:


Clearly the language cannot predict e.g. when users of a computer system will be active, so concurrency is generally nondeterministic. For information on how oracles have helped to support various forms of concurrency, see [[Concurrency with oracles]].
<blockquote>
<b>The Limit Computable or Approximation Model</b>


The use of oracles goes beyond programming languages:
There exists a sequence of Turing programs <math>\{P_t:t \in T\}</math> so that
<math>P_t</math> computes function <math>g_t</math> at time <math>{t \in T}</math>. There is not
necessarily any connection between different programs and computing may have to
start all over again with a new program as the time changes from <math>t</math> to <math>t+1</math>.


* Jennifer Hackett and Graham Hutton use them as the basis for an alternate semantics (rather than the more common stateful effects) in [https://www.cs.nott.ac.uk/~pszgmh/clairvoyant.pdf Call-by-Need Is Clairvoyant Call-by-Value].
Suppose a meteorologist receives data every second <math>t \in T</math> from weather
stations scattered across the country. The configuration at the meteorologist's
desk may be described using the Shoenfield Limit Lemma by a computable function
where <math>g_t</math> is the computable characteristic function of
<math>B_t</math>, the configuration of the meteorological computation at the end
of time <math>t</math>. The computable function <math>g_t</math> gives an algorithm to
compute the condition <math>B_t</math> at time <math>t</math> but it gives no relationship
between <math>B_t</math> and <math>B_{t+1}</math>. It will not be possible for the
meteorologist to run, let alone write a new program every second. How will the
meteorologist write a program to uniformly compute the index <math>g_t</math>
for <math>{t \in T}</math>?


* A brief mention appears in Conor McBride's representation of general recursion for use with total functional languages in [https://strathprints.strath.ac.uk/60166/1/McBride_LNCS2015_Turing_completeness_totally_free.pdf Turing-Completeness Totally Free].
<b>The Online Model With an Oracle Machine</b>


* Their use for [http://www.people.cs.uchicago.edu/~soare/Turing/shagrir.pdf online and interactive computing] is advocated by Robert Soare.
By the Shoenfield Limit Lemma there is a computably enumerable set <math>{A}</math> (or even
a <math>\Delta_2^0</math> set) and oracle machine <math>\Phi_e</math> such that
<math>B = \Phi_e^A</math>. Now the meteorologist can program the
algorithm <math>\Phi_e</math> into a computer once and for all at the start of the
day. Every second <math>{t \in T}</math> the meteorologist receives from the weather stations
the latest readings <math>A_t</math> which enter directly into that computer by
an network connection. The meteorologist does not (and cannot) change the
program <math>\Phi_e</math> every second. The algorithm simply receives the
“oracle” information <math>A_t</math> from the weather-station network as it is continually
updated, and computes the approximation <math>B_t(x) = \Phi_e^{A_t}(x)</math>.
The meteorologist's program then produces the next scheduled weather forecast for the day from the
algorithm's result. It is difficult to see how this meteorologist could have
carried out that activity using a batch processing, automatic machine
model, instead of an online model.
</blockquote>


* They have also been used in [https://www.cs.kent.ac.uk/people/staff/sao/documents/esop16.pdf functional big-step semantics] for supporting languages with I/O, in addition to nondeterminism.
...the oracle is a function of time <math>t \in T</math> with result
<math>A_t</math> providing input to the meteorologist's program.


== From oracles to ''pseudodata'' ==
=== The problem of choice ===


In his paper [https://academic.oup.com/comjnl/article-pdf/31/3/243/1157325/310243.pdf Nondeterminism with Referential Transparency in Functional Programming Languages], F. Warren Burton illustrates how oracle streams can be repurposed to convey other types of outside information, based on the classic example of [[Burton-style nondeterminism|nondeterministic choice]] - from that, Burton shows how this ''pseudodata'' can provide <tt>timestamps</tt> based on the current time:
But for the program's output - the forecasts - an element of choice is often
involved:


<haskell>
* the choice of time to send the forecasts to media outlets broadcasting to listeners or viewers - forecasts may need to be sent more frequently to regions experiencing more severe weather conditions.
-- section 2
data Tree a = Node { contents :: a,
                    left    :: Tree a,
                    right    :: Tree a }


-- section 7
* the choice of device - the meteorologist may need a hard copy of the latest forecast (or some part thereof) for research purposes.
data Timestamp  -- abstract, possibly builtin
stamp :: !Timestamp -> Timestamp
compare :: Timestamp -> Timestamp -> Integer -> Bool
</haskell>


He also hints as to how the current size of available storage can be made available.
Choices can also affect the program itself - the meteorologist may for
some reason decide to intervene while the program is running (perhaps
restarting it to provide more accurate forecasts after software upgrades).


Practical examples of ''pseudodata'' include:
In contrast, output is a simple matter for a function - if there is any,
it all goes to its caller! Therefore interactive choice requires something
more than functions alone; it usually appearing in the form of an abstract
type:


* '''clocks''' - in his thesis [https://core.ac.uk/download/9835633.pdf Functional Real-Time Programming: The Language Ruth And Its Semantics], Dave Harrison uses ''pseudodata'' to provide processes in a program with the current time.
* the various auxiliary types used in dialogues[https://hackage.haskell.org/package/dialogue <span></span>] - text and binary files, channels, <i>etc</i>.  


* '''supplies''' - In their functional pearl [https://www.cambridge.org/core/services/aop-cambridge-core/content/view/763DE73EB4761FDF681A613BE0E98443/S0956796800000988a.pdf/functional_pearl_on_generating_unique_names.pdf On generating unique names], Lennart Augustsson, Mikael Rittri and Dan Synek show how ''pseudodata'' can make Peter Hancock's <tt>name_supply</tt> viable for regular use. A small implementation by Iavor Diatchki [https://hackage.haskell.org/package/value-supply is available] in [https://hackage.haskell.org Hackage].
* the type of the final result returned by a nested sequence of CPS calls[https://dl.acm.org/doi/pdf/10.1145/165180.165199 <span></span>];


=== Extra parameters and arguments ===
* the type of the state passed through all the calls which require it[https://www.cambridge.org/core/services/aop-cambridge-core/content/view/2EFAEBBE3A19EA03A8D6D75A5348E194/S0956796800001258a.pdf/the-ins-and-outs-of-clean-io.pdf <span></span>];


While they recognise its preservation of referential transparency, in their paper [https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.46.1260&rep=rep1&type=pdf Programming Reactive Systems in Haskell], Sigbjørn Finne and Simon Peyton Jones also raise one possible annoyance with Burton's approach - the need to manually disperse ''pseudodata'' as additional arguments or parameters within programs.
* the monadic, comonadic or arrow types of online actions[https://web.archive.org/web/20051212060309/http://www.cse.ogi.edu/PacSoft/publications/phaseiiiq10papers/codata.pdf <span></span>][https://hackage.haskell.org/package/io-machine <span></span>];


As it happened, the first hints of a solution was already present when Burton's paper was first published, and now forms part of the standard <code>Prelude</code> for Haskell. Using the [https://downloads.haskell.org/~ghc/7.8.4/docs/html/users_guide/bang-patterns.html bang-patterns] extension:
Another option is to use an structured value of unbounded size:


<haskell>
* lazy lists, for incremental streaming[https://arxiv.org/pdf/1907.11354.pdf <span></span>];
-- for GHC 8.4.3
{-# LANGUAGE BangPatterns, FlexibleInstances, OverlappingInstances #-}


instance Monad ((->) (Tree a)) where
* lazy trees, for providing subtrees to various parts of the program[https://dspace.stir.ac.uk/bitstream/1893/12116/1/Harrison%20-%20thesis.pdf <span></span>].
    return x = \(!_) -> x
    m >>= k  = \t -> case m (left t) of !x -> k x (right t)
</haskell>


making use of the fact that the partially-applied function type <code>forall a . (->) a</code> is monadic.


[[Category:Code]]
[[Category:Code]]
[[Category:Nondeterminism]]
[[Category:Nondeterminism]]

Revision as of 04:00, 12 December 2024

What an oracle is

It was the work of Emil Post and others that established the oracle more formally:

Now suppose instead, says Turing   in effect, this situation obtains with the following modification. That at certain times the otherwise machine determined process raises the question is a certain positive integer in a given recursively enumerable set S2 of positive integers, and that the machine is so constructed that were the correct answer to this question supplied on every occasion that arises, the process would automatically continue to its eventual correct conclusion.23

23Turing picturesquely suggests access to an “oracle” which would supply the correct answer in each case. The “if” of mathematics is however more conducive to the development of a theory.

Recursively enumerable sets of positive integers and their decision problems (page 311).

Of interest here is the phrase the otherwise machine determined process - what answers the question is separate from that process. This implies:

  • an oracle cannot be computable.
If it was, it could also be computed by the machine-determined process.
  • an oracle doesn't access the internal state of the machine that calls it.
It only needs the positive integer of interest to supply the required answer, with all other actions being the responsibility of the machine-determined process.
  • an oracle returns a boolean result.
There are only two definite answers to the question:
is a certain positive integer in a given recursively enumerable set S2 of positive integers
and they can be mapped to the boolean values True and False.

Hence the oracle is a noncomputable function - originally a predicate, but now more commonly a function returning a wider range of values. This makes the use of oracles highly relevant to languages intended to preserve referential transparency, such as Haskell.

An adapted example

Based on page 42 of 76 in Turing-Post Relativized Computability and Interactive Computing:

The Limit Computable or Approximation Model

There exists a sequence of Turing programs {Pt:tT} so that Pt computes function gt at time tT. There is not necessarily any connection between different programs and computing may have to start all over again with a new program as the time changes from t to t+1.

Suppose a meteorologist receives data every second tT from weather stations scattered across the country. The configuration at the meteorologist's desk may be described using the Shoenfield Limit Lemma by a computable function where gt is the computable characteristic function of Bt, the configuration of the meteorological computation at the end of time t. The computable function gt gives an algorithm to compute the condition Bt at time t but it gives no relationship between Bt and Bt+1. It will not be possible for the meteorologist to run, let alone write a new program every second. How will the meteorologist write a program to uniformly compute the index gt for tT?

The Online Model With an Oracle Machine

By the Shoenfield Limit Lemma there is a computably enumerable set A (or even a Δ20 set) and oracle machine Φe such that B=ΦeA. Now the meteorologist can program the algorithm Φe into a computer once and for all at the start of the day. Every second tT the meteorologist receives from the weather stations the latest readings At which enter directly into that computer by an network connection. The meteorologist does not (and cannot) change the program Φe every second. The algorithm simply receives the “oracle” information At from the weather-station network as it is continually updated, and computes the approximation Bt(x)=ΦeAt(x). The meteorologist's program then produces the next scheduled weather forecast for the day from the algorithm's result. It is difficult to see how this meteorologist could have carried out that activity using a batch processing, automatic machine model, instead of an online model.

...the oracle is a function of time tT with result At providing input to the meteorologist's program.

The problem of choice

But for the program's output - the forecasts - an element of choice is often involved:

  • the choice of time to send the forecasts to media outlets broadcasting to listeners or viewers - forecasts may need to be sent more frequently to regions experiencing more severe weather conditions.
  • the choice of device - the meteorologist may need a hard copy of the latest forecast (or some part thereof) for research purposes.

Choices can also affect the program itself - the meteorologist may for some reason decide to intervene while the program is running (perhaps restarting it to provide more accurate forecasts after software upgrades).

In contrast, output is a simple matter for a function - if there is any, it all goes to its caller! Therefore interactive choice requires something more than functions alone; it usually appearing in the form of an abstract type:

  • the various auxiliary types used in dialogues - text and binary files, channels, etc.
  • the type of the final result returned by a nested sequence of CPS calls;
  • the type of the state passed through all the calls which require it;
  • the monadic, comonadic or arrow types of online actions;

Another option is to use an structured value of unbounded size:

  • lazy lists, for incremental streaming;
  • lazy trees, for providing subtrees to various parts of the program.