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