[MLton-user] Extended Basis Library: proposed patches to MONAD_EX,
MONADP_EX, and MkMonad
Geoffrey Alan Washburn
geoffw at cis.upenn.edu
Fri Mar 23 06:42:39 PST 2007
More additions to MONAD_EX and MONADP_EX
# I decided to name the function I had been calling »lift«, »pure«.
There is already a function named »lift« in the WHEN signature,
though I think that function may be more commonly called »join«.
»hoist« was longer and more obscure. I took the idea of »pure«
from Haskell Arrows. It kind of emphasizes that it is taking a
function that is »pure«, at least with respect to the given monad,
and making it »effectful«.
# Added »thunk« and »ignore« functions
# Added composition, »oo«, for computations. One idea I had was to
name this »O« (capital "o" if your font doesn't clearly distinguish
between 0 and O) but I'm not sure how popular that would be.
# Replaced »mk« with »mkFold« which acts a little more like a fold,
and used it to implement »foldl« and »foldr«.
# Added »seqWithPartial« to correspond with »mapPartial«.
# Added the »tabulate« function. I think the implementation could
be better, but I think the thing to do is to add some more general
unfolding functions in the near future.
# Defined »mapFst« and »mapSnd« because they seem to come up fairly
often. I'm open to suggestions for better names. I defined them
using two helpers »pairFst« and »pairSnd« which seem like they
would be good combinators to include in PRODUCT_TYPE, though again
probably with better names.
# Generalized »sum« in MONADP_EX to »sumWith«.
# Defined a »non-deterministic« choice operator »choose« for
MONADP_EX. However the current design isn't particularly »fair«.
Specifically, I anticipate for the constraint solver I'm working
on, it will lead to loops as it will always choose between
assumptions in the same order. Simple solution would be to
permute and then build the sum. I would be interested to hear
other proposals.
Index: ext-basis/detail/concept/mk-monad.fun
===================================================================
--- ext-basis/detail/concept/mk-monad.fun (revision 5463)
+++ ext-basis/detail/concept/mk-monad.fun (working copy)
@@ -5,7 +5,7 @@
*)
functor MkMonad (Core : MONAD_CORE) : MONAD = struct
- infix >> >>& >>* >>= >>@
+ infix >> >>& >>* >>= >>@ oo
open Core
type 'a func = 'a monad
fun map f aM = aM >>= return o f
@@ -14,19 +14,52 @@
fun fM >>@ aM = map Fn.\> (fM >>* aM)
fun aM >>& bM = map Product.& (aM >>* bM)
fun aM >> bM = map #2 (aM >>* bM)
+
+ fun pure f = return o f
+ fun thunk thk = return () >>= pure thk
+
+ fun ignore m = m >> return ()
+ fun y2zM oo x2yM = (fn x => x2yM x >>= y2zM)
+
local
- fun mk fin comb x2yM ac =
- fn [] => return (fin ac)
- | x::xs => x2yM x >>= (fn y => mk fin comb x2yM (comb (y, ac)) xs)
+ fun mkFold fM b fin =
+ fn [] => return (fin b)
+ | x::xs => fM (x, b) >>= (fn b' => mkFold fM b' fin xs)
in
- fun seqWith x2yM = mk rev op :: x2yM []
- fun appWith x2yM = mk ignore ignore x2yM ()
+ fun foldl fM b = mkFold fM b Fn.id
+ fun foldr fM b = (foldl fM b) o List.rev
+
+ fun seqWith x2yM = mkFold (fn (x, xs') => x2yM x >>= (fn x' =>
return (x'::xs'))) [] List.rev
+ fun appWith x2yM = foldl (ignore o x2yM o Pair.fst) ()
+
fun seq xMs = seqWith Fn.id xMs
fun app xMs = appWith Fn.id xMs
+
+ fun seqWithPartial x2yM =
+ mkFold (fn (x, xs') => x2yM x >>= (fn SOME x' => return
(x'::xs') | NONE => return xs')) [] List.rev
end
- fun ignore m = m >> return ()
+
fun when b m = if b then m else return ()
fun unless b m = if b then return () else m
+
+ local
+ fun tabulateTail f n m ac =
+ if n = m then
+ return (List.rev ac)
+ else
+ f m >>= (fn x => tabulateTail f n (m + 1) (x::ac))
+ in
+ fun tabulate n f = tabulateTail f n 0 []
+ end
+
+ local
+ fun pairFst x y = (y, x)
+ fun pairSnd x y = (x, y)
+ in
+ fun mapFst x2yM (x, z) = x2yM x >>= (pure o pairFst)
+ fun mapSnd x2yM (z, x) = x2yM x >>= (pure o pairSnd)
+ end
+
end
functor MkMonadP (Core : MONADP_CORE) : MONADP = struct
@@ -34,5 +67,13 @@
structure Monad = MkMonad (Core)
open Monad Core
type 'a monadp_ex = 'a monad
- fun sum [] = zero | sum [x] = x | sum (x::xs) = x <|> sum xs
+
+ fun sumWith x2yM =
+ fn [] => zero
+ | [x] => x2yM x
+ | x::xs => x2yM x <|> sumWith x2yM xs
+
+ fun sum ms = sumWith Fn.id ms
+ fun choose xs = sumWith return xs
+
end
Index: ext-basis/public/export/common.sml
===================================================================
--- ext-basis/public/export/common.sml (revision 5463)
+++ ext-basis/public/export/common.sml (working copy)
@@ -26,6 +26,7 @@
signature MONADP_CORE = MONADP_CORE
signature MONAD_CORE = MONAD_CORE
signature MONAD_EX = MONAD_EX
+signature MONADP_EX = MONADP_EX
signature MONAD_WS = MONAD_WS
signature MONAD_STATE = MONAD_STATE
signature MONADP_STATE = MONADP_STATE
Index: ext-basis/public/concept/monad.sig
===================================================================
--- ext-basis/public/concept/monad.sig (revision 5463)
+++ ext-basis/public/concept/monad.sig (working copy)
@@ -39,12 +39,24 @@
val >>* : 'a monad_ex * 'b monad_ex -> ('a * 'b) monad_ex
val >>@ : ('a -> 'b) monad_ex * 'a monad_ex -> 'b monad_ex
+ val pure : ('a -> 'b) -> 'a -> 'b monad_ex
+ (** {pure f == return o f} *)
+
+ val thunk : 'a Thunk.t -> 'a monad_ex
+ (** {thunk thk == return () >>= pure thunk} *)
+
val seq : 'a monad_ex List.t -> 'a List.t monad_ex
val seqWith : ('a -> 'b monad_ex) -> 'a List.t -> 'b List.t monad_ex
+ val seqWithPartial : ('a -> 'b Option.t monad_ex) -> 'a List.t ->
+ 'b List.t monad_ex
val app : 'a monad_ex List.t -> unit monad_ex
val appWith : ('a -> 'b monad_ex) -> 'a List.t -> unit monad_ex
+ val oo : ('b -> 'c monad_ex) * ('a -> 'b monad_ex) -> 'a ->
+ 'c monad_ex
+ (** {f2 oo f1 == (fn x => f1 x >>= f2) } *)
+
val ignore : 'a monad_ex -> unit monad_ex
(** {ignore m == (m >> return ())} *)
@@ -53,6 +65,26 @@
val unless : bool -> unit monad_ex -> unit monad_ex
(** {unless b m == if b then (return ()) else m} *)
+
+ val tabulate : int -> (int -> 'a monad_ex) -> 'a List.t monad_ex
+ (**
+ * Tabulate is a version of List.tabulate that can use
+ * functions that produce computations.
+ *
+ * {tabulate n f ==
+ * (f 0) >>= (fn x0 => (f 1) >>= ...
+ * (fn xn >>= return [x1, ..., xn]))}
+ *
+ * The actual implementation is tail recursive. *)
+
+ val foldl : ('a * 'b -> 'b monad_ex) -> 'b -> 'a list -> 'b monad_ex
+ val foldr : ('a * 'b -> 'b monad_ex) -> 'b -> 'a list -> 'b monad_ex
+
+ val mapFst : ('a -> 'c monad_ex) -> ('a, 'b) Pair.t ->
+ ('c, 'b) Pair.t monad_ex
+ val mapSnd : ('b -> 'c monad_ex) -> ('a, 'b) Pair.t ->
+ ('a, 'c) Pair.t monad_ex
+
end
signature MONAD = sig
@@ -71,6 +103,8 @@
signature MONADP_EX = sig
type 'a monadp_ex
val sum : 'a monadp_ex List.t -> 'a monadp_ex
+ val sumWith : ('a -> 'b monadp_ex) -> 'a List.t -> 'b monadp_ex
+ val choose : 'a List.t -> 'a monadp_ex
end
signature MONADP = sig
More information about the MLton-user
mailing list