This now appears to work!!

//////////////////////////////////////////
#import <flx.flxh>

typeclass Monad [M: TYPE->TYPE] {
  // elimination
  virtual fun thn[a,b]: M a * (a -> M b) -> M b;

  // introduction
  virtual fun ret[a]: a -> M a;
  virtual fun fail[a]: string -> M a;
}

typedef fun Maybe (t:TYPE):TYPE=>opt[t];

instance Monad [the Maybe] {
  fun thn[a,b] (x:Maybe a, f:a -> Maybe b) =>
    match x with
    | None[a] => None[b]
    | Some ?x => f x
    endmatch
  ;

  fun ret[a](x:a):Maybe a => Some x;
  fun fail[a] (x:string): Maybe a => None[a];
}

#infix 10 ">>=" thn

fun madd(x:double) (y:double):opt[double]=>Some (y+x);
fun msub(x:double) (y:double):opt[double]=>Some (y-x);
fun mmul(x:double) (y:double):opt[double]=>Some (y*x);
fun mdiv(x:double) (y:double):opt[double]=>
  if x == 0.0 then None[double] else Some (y/x) endif
;
fun mneg(x:double):opt[double]=>Some (-x);

open Monad[the Maybe];

proc show(r:Maybe double) {
   match r with
  | Some ?x => { print x; }
  | None => { print "divide by zero somewhere"; }
  endmatch; endl;
}

var x1 = 2.7; var y1 = 1.2; var z = 0.0;
{
  var r = ret x1 >>= msub y1 >>= mdiv z;
  show r; 
};

{
  var r = ret x1 >>= msub y1 >>= mdiv 2.0;
  show r;
};

//////////////////////////////////////////

First, we introduce a Monad typeclass. This is similar to 
the one used in Haskell except that we use the signature:

M a * (a -> M b) -> M b

with a product instead of curry form as used by Haskell:

M a -> (a -> M b) -> M b

We do this because Felix infix operators take a tuple
argument (whereas it seems Haskell's are curried).

I have left out the axioms .. however unlike Haskell we can
actually assert them!

I then defined the simple 'Maybe' monad, which is standard
in Haskell: it is a monad based on the 'opt' type.

Then I define monadic operations for addition, subtraction
etc on doubles .. they return type 'Maybe double' which is 
of course the same as opt[double].

These functions are curried and operate in reverse order
because the monadic argument is a single argument function.
Thus for example:

        msub 10.0

is a function which substracts its argument FROM 10.
So the argument is the RHS of infix operator like:

        10.0 - ???


Similarly

        mdiv 0.0

divides its argument BY zero. This just return None,
no matter what the argument is. Now you can use
the monadic combinators to write a monadic form of

        (x1 - y1) / z

as this:

  var r = ret x1 >>= msub y1 >>= mdiv z;

You should note this is just composition -- but it is
MONADIC composition because our functions accept
double, but return Maybe double and thus can't be
chained together with an ordinary compostion operator.

The 'ret' at the start lifts the initial value into
the monad so the subsequent combinator can start with
the right type of value. The composition is left associative,
and you should read it like 'object oriented' method applications:
from left to right. Rather strange for an FPL using the 
traditional forward polish (prefix) notation.

To make all this work only seemed to require some minor
changes after the previous work (however it isn't clear
I did everything right so expect some of the usual weird errors!)

I have made lambdas comparable by alpha-equivalence,
that is, two 'type functions' are equal if their body
terms are the same, except for the names of parameters.
This is essential in the example above where UNLIKE
Haskell 'Maybe' is just an alias for a type lambda.
(in Haskell functors are nominally typed).


-- 
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
Felix-language@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/felix-language

Reply via email to