[m-dev.] for review: add web page comparing with Haskell

Fergus Henderson fjh at cs.mu.OZ.AU
Sun Mar 11 19:55:31 AEDT 2001


Estimated hours taken: 3

w3/information/Makefile:
w3/information/include/documentation.inc:
w3/information/comparison_with_haskell.php3:
w3/information/include/comparison_with_haskell.php3:
	Add a page comparing Mercury's type system with
	that of Haskell 98.

The diff is below, but you may prefer to review the
generated HTML, which I've installed at
<http://www.cs.mu.oz.au/~fjh/tmp/comparison_with_haskell.html>.

cvs diff: Diffing .
Index: Makefile
===================================================================
RCS file: /home/mercury1/repository/w3/information/Makefile,v
retrieving revision 1.13
diff -u -d -u -r1.13 Makefile
--- Makefile	2000/10/26 13:35:24	1.13
+++ Makefile	2001/03/11 08:53:46
@@ -2,6 +2,7 @@
 
 ROOT=..
 HTML= 	benchmarks.html 	\
+	comparison_with_haskell.html \
 	developer.html 		\
 	documentation.html 	\
 	events.html		\
Index: comparison_with_haskell.php3
===================================================================
RCS file: comparison_with_haskell.php3
diff -N comparison_with_haskell.php3
--- /dev/null	Fri Mar  2 14:16:41 2001
+++ comparison_with_haskell.php3	Sun Mar 11 18:29:26 2001
@@ -0,0 +1,9 @@
+<HTML>
+<?
+    $title="Comparing Mercury and Haskell";
+    $dir="information";
+    $root="..";
+    $include="comparison_with_haskell.inc";
+    include "$root/include/template.inc"
+?>
+</HTML>
cvs diff: Diffing bench
cvs diff: Diffing developers
cvs diff: Diffing dotnet
cvs diff: Diffing events
cvs diff: Diffing events/images
cvs diff: Diffing include
Index: include/comparison_with_haskell.inc
===================================================================
RCS file: comparison_with_haskell.inc
diff -N comparison_with_haskell.inc
--- /dev/null	Fri Mar  2 14:16:41 2001
+++ comparison_with_haskell.inc	Sun Mar 11 19:52:43 2001
@@ -0,0 +1,236 @@
+<h2>Comparing Mercury with Haskell</h2>
+
+Mercury has a lot in common with functional languages.
+Functional programmers who are familiar with languages
+such as ML and Haskell often ask how Mercury compares
+with those languages.
+
+<p>
+
+This web page contains a comparison between the type systems of Mercury and
+Haskell 98.  The reason for comparing with Haskell 98 is that Mercury's type
+system is more similar to that of Haskell than that of ML, and Haskell 98 is
+probably the best documented / most well-known variant of Haskell.  Of course
+Hugs and ghc have a lot of extensions of Haskell 98, so in some sense this is
+not a "fair" comparison.
+
+<p>
+
+As well as listing the differences in type systems, we also describe
+some of the differences in module systems, since there are some close
+interactions between the type systems and the module systems.
+
+<p>
+
+There are many other areas in which Mercury and Haskell 98
+differ, including
+	<ul>
+	<li> syntax,
+	<li> the way in which the semantics is normally described
+	     (predicate calculus versus lambda calculus),
+	<li> operational semantics (laziness / order of evaluation),
+	<li> exception handling,
+	<li> treatment of I/O,
+	<li> standard libraries,
+	<li> and of course support for logic programming,
+	</ul> but we don't yet have point-by-point description of all of those
+differences.
+
+<p>
+
+The type systems of Mercury and Haskell 98 are similar in that they both have
+the following features:
+
+<ul>
+	<li> discriminated union (d.u.) types, with support for named fields
+	<li> type synonyms
+	<li> higher-order function types (and lambda expressions)
+	<li> tuple types
+	<li> parametric polymorphism:
+		<ul>
+		<li> polymorphic d.u. types
+		<li> polymorphic type synonyms
+		<li> polymorphic functions
+		<li> polymorphic recursion
+		</ul>
+	<li> type classes
+	<li> type inference
+	<li> a similar set of basic types
+</ul>
+
+They differ in the following ways:
+
+<ul>
+	<li> Different syntax (obviously). <br>
+	  But in particular:
+	  	<ul>
+		<li> Haskell 98 lexically distinguishes
+		  constructors (uppercase initial letter)
+		  from functions/variables (lowercase initial letter)
+		  whereas Mercury distinguishes variables
+		  (uppercase initial letter)
+		  from functions/constructors (lowercase initial letter).
+	  	<li> Haskell 98 permits nested function definitions,
+		  Mercury doesn't.  In Mercury you can use variables
+		  with higher-order type and initialize them with
+		  lambda expressions, of course, but variables
+		  are always monorphically typed and functions
+		  defined using lambda expressions can't be recursive.
+		</ul>
+
+	<li> Haskell 98 has the infamous monomorphism restriction
+	  which means that variables are monomorphic
+	  unless you give an explicit polymorphic type
+	  declaration for them.
+	  In Mercury variables are always monomorphic,
+	  but because of the lexical distinction between
+	  variables and functions, that doesn't seem to lead
+	  to the same confusion that the Haskell monomorphism
+	  restriction causes.
+
+	<li> Mercury requires type declarations for all functions exported
+	  from a module, Haskell 98 doesn't, at least in theory
+	  (in practice, current Haskell implementations effectively
+	  require explicit type declarations [or worse] in the case of
+	  mutually recursive modules).
+
+	<li> For polymorphic recursion,
+	  Haskell 98 requires an explicit type declaration,
+	  whereas Mercury allows polymorphic recursion with
+	  type inference, using a user-tunable iteration limit
+	  to ensure termination of the type inference process.
+
+	<li> Haskell 98 allows type classes to define default implementations
+	  for methods, whereas Mercury doesn't.
+
+	<li> Haskell 98 allows type class instances to leave some methods
+	  undefined, in which case calls to such methods will be
+	  run-time errors, whereas Mercury treats undefined methods as
+	  a compile time error and requires users to explicitly define
+	  methods to call <code>error</code> if that is what they want.
+
+	<li> Haskell 98 supports constructor classes, Mercury doesn't.
+
+	<li> Haskell 98's standard library makes extensive use of
+	  type classes, Mercury's doesn't (mainly for historical reasons).
+
+	<li> Mercury allows multi-parameter type classes
+	  (however, we don't support functional dependencies,
+	  and there are some restrictions on the forms of
+	  instance declarations, so this may not be quite as
+	  useful as it might first appear).
+
+	<li> Mercury supports existentially typed functions,
+	  and existentially typed data types, whereas Haskell 98 doesn't
+	  (Hugs, ghc and other Haskell implementations support existentially
+	  typed data types, but not existentially typed functions).
+
+	<li> Mercury supports "ad-hoc" overloading (there can be more
+	  than one constructor, function or class method with the same
+	  name, and the compiler will determine which one each occurence
+	  of that name refers to based on the types),
+	  Haskell 98 doesn't.
+	  (Of course if you make significant use of ad-hoc overloading,
+	  this can lead to ambiguities that type checker can't resolve;
+	  if such ambiguities occur, you need to use explicit type
+	  declarations to resolve them, rather than relying on type
+	  inference.)
+
+	<li> In Haskell 98, functions always take a single argument;
+	  multiple arguments are handled using currying or tuples.
+	  In Mercury, functions can take multiple arguments, and
+	  such functions have a type distinct from functions taking
+	  tuples or functions returning functions.
+	  (Haskell's approach leads to more elegant source code;
+	  Mercury's approach has a simpler and more predictable
+	  performance model.)
+
+	<li> The semantics of Haskell 98 say that each type has "bottom"
+	  as an extra element, to handle laziness.
+	  In Mercury, laziness is treated as part of the operational
+	  semantics rather than the declarative/denotational semantics,
+	  so you don't get the extra "bottom" element in each type.
+	  (To a first approximation, Mercury is eager, not lazy.
+	  But, since that's a difference in the operational semantics,
+	  rather than in the type system, we won't go into the
+	  details here, except to note that the first approximation
+	  is not the full story.)
+
+	<li> Haskell 98 has two constructs for introducing
+	  discriminated union types, <code>data</code> and <code>newtype</code>,
+	  which differ in laziness and representation,
+	  whereas Mercury uses just one, <code>:- type</code>;
+	  Mercury doesn't support lazy constructors,
+	  so the laziness distinction is not applicable,
+	  and in Mercury the representation effect of <code>newtype</code> is
+	  automatic for any type with one constructor and one argument.
+
+	<li> Mercury supports nested modules, Haskell 98 doesn't.
+	  So in Mercury you can have abstract types whose definition
+	  is only visible in a sub-module, rather than in the
+	  whole of the (outermost) module that contains them.
+
+	<li> Mercury's module system allows instance declarations
+	  to be public (exported) or local (private), whereas
+	  in Haskell instance declarations are always exported.
+
+	<li> Mercury has predicates as well as functions
+	  (predicate types are distinct from functions returning bool).
+	  This includes supporting existentially typed predicates,
+	  predicates as type class methods, predicate lambda expressions,
+	  and higher-order predicate types.
+
+	<li> Mercury supports optional dynamic typing, Haskell 98 doesn't.
+	  (Hugs/ghc do.  However, their approach of implementing this
+	  is a bit cumbersome, since the user has to explictly declare
+	  instances of <code>Typeable</code>, and its use of an unchecked
+	  cast would be problematic in the presence of untrusted code.)
+
+	<li> The treatment of equality, comparison, automatically derived
+	  classes, and RTTI differs considerably between the two
+	  languages.  Haskell 98 has built-in type classes Eq, Ord, Enum,
+	  Bounded, Read, and Show, and allows instances for these to be
+	  automatically derived, if the programmer writes
+	  e.g. <code>deriving Eq</code>
+	  on the type declaration.  In Mercury, equality is a language
+	  construct, not a class method like <code>==</code> in Haskell.
+	  Mercury allows user-defined equality, but because this
+	  alters the semantic notion of equality, it has very different
+	  effects in Mercury than defining <code>==</code> does in Haskell.
+	  Mercury's RTTI system allows constructing and deconstructing
+	  arbitrary types at runtime, and comparison and (de)serialization
+	  (compare, read, and write) are implemented using this.
+
+	<li> Mercury's standard library provides a referentially
+	  transparent interface to mutable variables (the store
+	  module -- using existential types and unique modes),
+	  that is usable from non-I/O code; Haskell 98's doesn't,
+	  probably because it would require extensions to the Haskell 98
+	  type system.  (Hugs/ghc do provide such an interface,
+	  using higher-order functions with explicit universal
+	  quantification, and monads, rather than existential types
+	  and unique modes.  Other Haskell implementations may do so
+	  too.)
+</ul>
+
+<p>
+
+Some other differences are related to Mercury's mode system.
+Some things which in other languages are part of the type system
+are in Mercury handled by the mode system.  In particular,
+
+	<ul>
+	<li> Mercury's mode system provides support for subtypes.
+	  For example, you can declare that a function whose
+	  argument is a discriminated union type accepts only
+	  a subset of the possible constructors for that type,
+	  and the mode system will enforce this.
+
+	<li> Mercury's mode system provides support for uniqueness,
+	  similar to linear types or unique types.  (However,
+	  currently there are some significant limitations with
+	  this, in particular unique modes can only be used
+	  at the top level of a term.)
+	  
+	</ul>
+
Index: include/documentation.inc
===================================================================
RCS file: /home/mercury1/repository/w3/information/include/documentation.inc,v
retrieving revision 1.4
diff -u -d -u -r1.4 documentation.inc
--- include/documentation.inc	2001/03/11 08:26:53	1.4
+++ include/documentation.inc	2001/03/11 08:33:12
@@ -57,6 +57,14 @@
 	<a href="doc/transition_guide.ps.gz">Postscript</a>
 	<p>
 
+	<li> <strong>Comparing Mercury and Haskell</strong><br>
+	A point-by-point comparison of some of the differences
+	between Mercury and Haskell 98, in particular with
+	regard to their type systems.<p>
+
+	Available in 
+	<a href="comparison_with_haskell.html">HTML</a> only.<p>
+
 	<li> <strong>Frequently Asked Questions</strong><br>
 	Information on common programming errors, problems caused by
 	unimplemented Mercury features and where to turn for help.<p>
cvs diff: Diffing papers
cvs diff: Diffing reports
-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
                                    |  of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh>  |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list