Features declared obsolete at release two

At release two of Miranda in 1989 it was decided to remove the following
features from the the language
        algebraic types with laws (=>)
        algebraic types with field annotations for strictness (!)
These  features  had been found to be of rather marginal value, and they
introduce significant and undesirable complications into the semantics.

For the time being they are still supported by the compiler,  so  no-one
loses  a  working  script,  but  they  are  no longer officially part of
Miranda and their use now attracts an `obsolete feature' warning at each
compilation.  At some stage in the future (probably at the next release)
they will cease to be supported by the compiler.

Laws

Here is a method for translating Miranda code using laws into equivalent
code  not  using  this  feature.   We  take  an  example  from the Nancy
paper (Turner 1985), of self-ordering lists, for illustration

      --------------------------------------------------------
     |                                                        |
     |  olist ::= Onil | Ocons num olist                      |
     |                                                        |  
     |  Ocons a (Ocons b x) => Ocons b (Ocons a x), if a>b    |
     |                                                        |
      --------------------------------------------------------

For each constructor which has laws associated with  it  (in  this  case
Ocons)  we introduce a new function name (`ocons' say).  Now we make two
changes to the script

  1) Throughout the script (including the rhs of the laws)  replace  all
right-hand-side  occurences of the lawful constructors by the associated
function names.  Only the `left-hand-side' uses of the constructor, i.e.
in pattern matching, are left alone.

  2) Turn  each  law  into  a  function  definition,  by  replacing  the
outermost  occurrence  of  the  constructor on the lhs of the law by the
associated function name, and replacing each `=>' by `='.  We must  also
add  a last case to the function definition, stating that it is equal to
a call of its associated constructor on the same arguments if no earlier
case applies.

The definition of olist now looks like this

      -------------------------------------------------------- 
     |                                                        |
     |  olist ::= Onil | Ocons num olist                      |
     |                                                        |  
     |  ocons a (Ocons b x) = ocons b (ocons a x), if a>b     |
     |  ocons a x = Ocons a x                                 |
     |                                                        |
      --------------------------------------------------------

and throughout the rest of the code any occurences of `Ocons' other than
in  pattern matching is likewise replaced by the function `ocons'.  This
translation must preserve  the  behaviour  of  the  script  (because  it
corresponds exactly to the way in which laws are implemented).

[A comment on this translation:-
 Notice that the fact that objects  of  type  `olist'  are  ordered  now
depends  on  a  voluntary  discipline by the programmer - that he always
builds his olists by calling the function ocons, and never by using  the
raw constructor Ocons.  So the original script using laws had a security
about it that the translation no longer expresses  -  if  we  come  back
later   and   add  new  code,  we  might  `forget'  the  discipline  and
accidentally build a non-ordered olist, by calling Ocons directly.

 The proper solution to this is to make olist into an abstract data type
(although  this will involve a more radical rewrite of your script).  In
fact the main reason for dropping  lawful  types  from  Miranda  is  the
observation  that  the abstype declaration is a cleaner and more general
mechanism for introducing unfree types.

 For example here is a  possible  definition  of  ordered  lists  as  an
abstract type

	abstype olist
	with onil :: olist
	     ocons::num->olist->olist
	     ohd::olist->num
	     otl::olist->olist
	     oempty::olist->bool
	
	olist == [num] ||constraint: the list is kept ordered, see below
	ocons a (ocons b x) = b:ocons a x, a>b
        ocons a x = a:x, otherwise
	ohd = hd
	otl = tl
	oempty = (=[])

In the rest of the script we can manipulate olists ONLY by  calling  the
functions  declared  in  the  signature  of  the  abstype  (that is, the
information following the `with').  It is therefore logically impossible
to create a non-ordered olist.  One thing has been lost - in the rest of
the script we can no longer do pattern matching on olists - but that  is
a small price to pay for security.

end of comment]

Strictness annotations

The semantic effect of a strictness annotation (!) after a field  in  an
algebraic  type  definition  is  to make certain expressions evaluate to
BOTTOM (error or non-termination) that would otherwise have had a value.
It  therefore  follows that removing all the strictness annotations must
be semantically harmless - it cannot introduce an error into  a  working
program.

A secondary purpose of strictness annotations was to gain  some  control
over space behaviour by forcing some constructors to be call-by-value in
some of their arguments.  However, if you are  interested  in  modifying
the   space  behaviour  of  your  programs  by  changing  the  order  of
evaluation, you can always use `force' and `seq' to do this explicitly.

For example, if you wish data structure x to be fully  evaluated  before
being passed to function f, you can write
	seq (force x) (f x)

------------------------------------------------------------------------

Reference: D. A. Turner ``Miranda: A Non-Strict Functional Language with
Polymorphic   Types'',   Proceedings   IFIP   Conference  on  Functional
Programming  Languages  and  Computer   Architecture,   Nancy,   France,
September 1985 (Springer Lecture Notes in Computer Science 201:1-16).

this can be found at http://miranda.org.uk

