I have not read fully the link given previously on monad. So please ignore
if it is duplicate code of it . (some I copied,other I ignored temporary
for now )
Monad part 1 :
#include “share/atspre_define.hats”
#include “share/atspre_staload.hats”
datatype Maybe (a : t@ype) =
| Nothing (a) of ()
| Just (a) of (a)
abstype M (t@ype) = ptr
extern
fun{a:t@ype} ret : a -> M (a)
typedef cfun (a:t@ype,b:t@ype) = a - M (b)
extern
fun{a,b:t@ype} bind : (M (a) , cfun (a, b)) -> M (b)
assume M (a : t@ype) = Maybe (a)
implement{a}
ret (x) = Just (x)
implement{a,b}
bind (m , f) =
case m of
| Nothing _ => Nothing
| Just (x) => f (x)
fun (* {a:t@ype} *)
print_maybe (ma : Maybe (int)) : void =
case ma of
| Nothing _ => println! (“Nothing”)
| Just (x) => println! (x)
datatype Expr =
| Val of Int
| Div of (Expr , Expr)
val ok = Div (Div ( Val (1972) , Val (2) ) , Val (23))
(* val err = Div (Val 2) (Div (Val 1) (Div (Val 2) (Val 3))) *)
val err = Div (Val (2) , Div (Val (1) , Div (Val (2) , Val (3))))
extern
fun div (m : int , n : int) : Maybe(int)
fun eval (e : Expr) : Maybe(int) =
case e of
| Val n => ret (n)
| Div (e1 , e2) =>
bind<int,int> (eval e1 ,
(lam m =>
bind<int,int> (eval e2,
(lam n => div (m,n)))))
implement
div (m , n) =
if n = 0
then Nothing ()
else ret (m / n)
datatype Opt (a:t@ype) =
| None of ()
| Some (a) of (a)
//assume M (a : t@ype) = Opt (a)
implement main0 () = () where {
val _ = println! (“Monad”)
val res1 = eval ok
val res2 = eval err
val _ = print_maybe (res1)
val _ = print_maybe (res2)
}
So now I can use monadic computation in ATS , but cannot use two different
monads in same program, for example I can use Maybe monad but not Opt
in given above code (right ?)
Maybe above is a higher kind or a type constructor : (t@ype -> type)
(right ?) .
So why not implement monads as given below
Monad Part 2 :
#include “share/atspre_define.hats”
#include “share/atspre_staload.hats”
datatype Maybe (a : t@ype) =
| Nothing (a) of ()
| Just (a) of (a)
typedef cfun (M:(t@ype -> type), a:t@ype,b:t@ype) = a - M (b)
extern
fun{a:t@ype}{H : (t@ype -> type)}
ret : a -> H (a)
extern
fun {a,b:t@ype}{H : (t@ype -> type)}
bind: (H (a) , cfun (H,a,b)) -> H (b)
implement(a)
ret (x) = Just (x)
implement(a,b)
bind<a,b> (ma , f) =
case ma of
| Nothing _ => Nothing
| Just (x) => f (x)
datatype Expr =
| Val of Int
| Div of (Expr , Expr)
val ok = Div (Div ( Val (1972) , Val (2) ) , Val (23))
val err = Div (Val (2) , Div (Val (1) , Div (Val (2) , Val (3))))
extern
fun div (m : int , n : int) : Maybe(int)
fun eval (e : Expr) : Maybe(int) =
case e of
| Val n => ret (n)
| Div (e1 , e2) =>
bind<int,int> (eval e1 ,
(lam m =>
bind<int,int> (eval e2,
(lam n => div (m,n)))))
implement
div (m , n) =
if n = 0
then Nothing ()
else ret (m / n)
fun (* {a:t@ype} *)
print_maybe (ma : Maybe (int)) : void =
case ma of
| Nothing _ => println! (“Nothing”)
| Just (x) => println! (x)
datatype Opt (a:t@ype) =
| None of ()
| Some (a) of (a)
implement(a)
ret (x) = Some (x)
implement(a,b)
bind<a,b> (ma , f) =
case ma of
| None _ => None
| Some (x) => f (x)
fun (* {a:t@ype} *)
print_opt (opt : Opt (int)) : void =
case opt of
| None _ => println! (“None”)
| Some (x) => println! (x)
implement main0 () = () where {
val _ = println! (“Monads”)
val mi = ret (100)
val _ = print_maybe (mi)
val res1 = eval ok
val res2 = eval err
val _ = print_maybe (res1)
val _ = print_maybe (res2)
val _ = print_opt (ret (1000))
}
Above code runs without any error.
Now I can use both Opt and Maybe in same program.
Is the above code correct and what does it mean to have (t@ype -> type) in
template arguments.
Thanks.