Difference between revisions of "Opting for oracles"

From HaskellWiki
Jump to: navigation, search
m (Final two sections reorganised)
m (Improved grammar; descriptions clarified)
 
(One intermediate revision by the same user not shown)
Line 19: Line 19:
 
== From oracles to ''pseudodata'' ==
 
== From oracles to ''pseudodata'' ==
   
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 oracles can be repurposed to make use of other types of outside information, based on the classic example of [[Burton-style nondeterminism|nondeterministic choice]]: from that, Burton shows how to provide the current time, using the example of <tt>timestamps</tt>:
+
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:
   
 
<haskell>
 
<haskell>
Line 33: Line 33:
 
</haskell>
 
</haskell>
   
He also hints as to how the current size of available storage can also be made available.
+
He also hints as to how the current size of available storage can be made available.
   
 
=== Extra parameters and arguments ===
 
=== Extra parameters and arguments ===
   
While they acknowledge Burton's technique does maintain referential transparency, in their paper [https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.49.695&rep=rep1&type=pdf On the Expressiveness of Purely Functional I/O Systems] Paul Hudak and Raman S. Sundaresh also raise one possible annoyance - the need to manually disperse subtrees as additional arguments or parameters within programs.
+
While they acknowledge Burton's technique does maintain 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 - the need to manually disperse ''pseudodata'' as additional arguments or parameters within programs.
   
 
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:
 
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:

Latest revision as of 14:10, 8 October 2021

Oracles, defined

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, preserves the referential transparency of the language being used.

This makes the use of oracles highly relevant to languages intended to preserve referential transparency, such as Haskell.

Oracles in use

The early use of oracles in programming languages focused on coping with the 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:

  • inside the language e.g. definitions which the computations share, or
  • outside of it e.g. hardware devices for storage, audiovisual or networking.

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.

(Of course, the use of oracles goes beyond programming languages e.g. Jennifer Hackett and Graham Hutton use them to alleviate some of the tedium associated with the classic state-centric semantics used to examine the operational behaviour of lazy programs - see Call-by-Need Is Clairvoyant Call-by-Value.)

From oracles to pseudodata

In his paper 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 nondeterministic choice: - from that, Burton shows how this pseudodata can provide timestamps based on the current time:

 -- section 2
data Tree a = Node { contents :: a,
                     left     :: Tree a,
                     right    :: Tree a }

 -- section 7
data Timestamp  -- abstract, possibly builtin
stamp :: !Timestamp -> Timestamp
compare :: Timestamp -> Timestamp -> Integer -> Bool

He also hints as to how the current size of available storage can be made available.

Extra parameters and arguments

While they acknowledge Burton's technique does maintain referential transparency, in their paper Programming Reactive Systems in Haskell, Sigbjørn Finne and Simon Peyton Jones also raise one possible annoyance - the need to manually disperse pseudodata as additional arguments or parameters within programs.

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 Prelude for Haskell. Using the bang-patterns extension:

 -- for GHC 8.4.3
{-# LANGUAGE BangPatterns, FlexibleInstances, OverlappingInstances #-}

instance Monad ((->) (Tree a)) where
    return x = \(!_) -> x
    m >>= k  = \t -> case m (left t) of !x -> k x (right t)

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