Felix now seems to support typeclasses with enough bells,
whistles, and boxed copies of the kitchen sink, to FINALLY
allow replacement of all the grubby macros for basic C types
in the standard library with something resembling sane
high level code.

Lots of testing is needed!

BE WARNED -- not all the error messages will be sane,
and there will probably be a some cases of infinite
loops in both the compiler and runtime code if you
mess up.

///////////////////////////////////////////////////////////
//
// The first thing to do is NOT include the standard library
//
//#import <flx.flxh>
//
// Now we need some I/O to report results
//

header '#include <iostream>';
proc print[t]:t="std::cout<<$1;";
proc endl:1="std::cout<<std::endl;";

//
// and some basic definitions 
//
typedef bool = 2;
typedef unit = 1;
fun lnot: 2->2 = "!$1";
typedef lvalue[t] = lval t;

//
// lift some arithmetic types from C to play with
//
ctypes short, int, long, ulong, float, double;
typedef ints = typesetof(short, int, long, ulong);

//
// A typeclass for equality
//
// Note eq,ne are defined in terms of each other
// so one of them had better be defined in every
// instance or we'll get an infinite loop at runtime
//
typeclass Eq[t] {
  virtual fun eq (x:t,y:t):bool => not (ne (x,y));
  virtual fun ne (x:t,y:t):bool => not (eq (x,y));
}

//
// an instance for some C integers
//

instance [t:ints] Eq[t] {
  fun eq: t * t -> bool = "$1==$2";
}

// total order
typeclass Tord[t]{
  inherit Eq[t];
  virtual fun lt: t * t -> bool; 
  virtual fun gt(x:t,y:t):bool =>lt(y,x);
  virtual fun le(x:t,y:t):bool => not (gt(x,y));
  virtual fun ge(x:t,y:t):bool => not (lt(x,y));
}

instance[t:ints] Tord[t]{
  fun lt: t * t -> bool = "$1<$2";
}

//
// additive symmetric group
//
// This typeclass includes a semantic specification!
//
typeclass Addgrp[t] {
  inherit Eq[t];
  virtual fun zero: 1 -> t;
  virtual fun add: t * t -> t;
  virtual fun inv: t -> t;
  virtual fun sub(x:t,y:t):t => add (x,inv y);
  virtual proc pluseq (x:lvalue[t],y:t){ x = x + y; }
  virtual proc minuseq (x:lvalue[t],y:t){ x = x - y; }
  reduce id (x:t): x+zero() => x;
  reduce id (x:t): zero()+x => x;
  axiom assoc (x:t,y:t,z:t): (x+y)+z == x+(y+z);
  reduce inv(x:t): x-x => zero();
  reduce inv(x:t,y:t): x+y-y => x;
  axiom sym (x:t,y:t): x+y == y+x;
}

// integers form a group under addition, at least locally
instance[t:ints] Addgrp[t] {
  fun zero: 1 -> t = "0" ;
  fun add: t * t -> t = "$1+$2" ;
  fun inv: t -> t = "-$1" ;
  fun sub: t * t -> t = "$1-$2" ;
  proc pluseq: lvalue[t] * t = "$1+=$2;";
  proc minuseq: lvalue[t] * t = "$1-=$2;";
}

//
// A multiplicative semi-group with unit
//
// Similar to a group, but lacking an inverse,
// it does have a cancellation law instead
// (0 has no inverse)
//
typeclass MultSemi1[t] {
  inherit Eq[t];
  virtual fun one: unit -> t;
  virtual fun mul: t * t -> t;
  virtual proc muleq: lvalue[t] * t;
  reduce id (x:t): x*one() => x;
  reduce id (x:t): one()*x => x;
  axiom assoc (x:t,y:t,z:t): (x*y)*z == x*(y*z);
  reduce cancel (x:t,y:t,z:t): x * z ==  y * z => x == y;
}

// integers form a semi-group under multiplication, at least locally
instance[t:ints] MultSemi1[t] {
  fun one: unit -> t = "1" ;
  fun mul: t * t -> t = "$1*$2" ;
  proc muleq: lvalue[t] * t = "$1*=$2;";
}

//
// A ring (with unit) is an additive group which 
// is also a multiplicative semi-group
//
typeclass Ring[t] {
  inherit Addgrp[t];
  inherit MultSemi1[t];
  axiom distrib (x:t,y:t,z:t): x * ( y + z) == x * y + x * z;
}

instance[t:ints] Ring[t] {}

//
// A division ring is a ring with unit which
// also supports division, except by 0
// [Note the bug: the precondition on 'div' cannot
// be stated except in a comment: this is mainly
// a syntax issue]
//
typeclass Dring[t] {
  inherit Ring[t];
  virtual fun div: t * t -> t; // pre t != 0
  virtual proc diveq: lvalue[t] * t;
  virtual fun mod : t * t -> t;
  virtual proc modeq: lvalue[t] * t;
}

//
// and of course integers form a division ring
//
instance[t:ints] Dring[t] {
  fun div: t * t -> t = "$1/$2" ;
  proc diveq: lvalue[t] * t = "$1/=$2;";
  fun mod : t * t -> t = "$1%$2" ;
  proc modeq: lvalue[t] * t = "$1%=$2;";
}

//
// now define some functions depending on 
// these typeclasses
//
fun g[t with Tord[t]] (x:t,y:t) => x >= y;
fun f[t with Dring[t], Eq[t]] (x:t,y:t) => x+y-y == x;

// 
// and test them with arguments which are ints
//
print$ g(1,2); endl;
print$ f(1,2); endl;

//
// finally check we can just open these things
//
{
  open Addgrp[int];
  val x = 10;
  val y = 42;
  print$ x+y-y; endl;
};

{
  open Dring[long];
  val x = 10L;
  val y = 42L;
  print$ x+y-y; endl;
};
//////////////////////////////////////////////////////////

In the above code a lot of highly sophisticated work
is being done!

You will note the use of 'specialisation views', binding
of typeclass instances to typeclasses, and constraint
checking -- not to mention real, executable semantics
for our ADTs which hopefully will be amenable to
proof and optimisation opportunities.

-- 
John Skaller <skaller at users dot sf dot net>
Felix, successor to C++: http://felix.sf.net


-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
Felix-language mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/felix-language

Reply via email to