* Re: Folding in ML (was "OCaml's formatting libraries")
@ 2007-11-12 1:20 Till Varoquaux
0 siblings, 0 replies; only message in thread
From: Till Varoquaux @ 2007-11-12 1:20 UTC (permalink / raw)
To: caml-list
On Nov 10, 2007 2:13 PM, Jon Harrop <jon@ffconsultancy.com> wrote:
> On Saturday 10 November 2007 15:43, Bünzli Daniel wrote:
> > Le 10 nov. 07 à 15:58, Jon Harrop a écrit :
> > > Functional unparsing requires a lot more code,
First let me say that formats are an Opt-in feature: don't like don't
use it. Although on a theoretical point of view I'm not fond of it I
use it on a daily basis. I guess you could say it's a pragmatic
solution. On one hand formats are a hack on the other they are very
useful (and AFAIK there's no way to implement parser combinators in
functional unparsing). That being said functional uparsing printf's
are not as bad as make them sound. It is also a very useful technique
to master: it is the answer to a general class of problems and can be
an elegant to hairy problems. A typical example could be function
transformations composition (take f°g°h when you want f ,g and h to
have eventual additional parameters).
That being there are more succinct solutions to the "printf" problem,
some of them have probably not be found. This is part of a family of
problems you could call the "folding" family. Here are some of the
hacks I know of, I 'd be interested in learning new ones:
let string_of_string s = s
(*
I) Functional unparsing.
This technique was first detailed by Olivier Danvy
(http://www.brics.dk/RS/98/12/).
*)
type ('a,'b) format = (string -> 'a) -> string -> 'b
let (!)f : (_,_) format = fun k acc v -> k (acc ^ (f v))
let (++) (f:(_,_)format) (g:(_,_)format) : (_,_)format = fun x -> f (g x)
let int: (_,_) format = fun x -> !string_of_int x
let string : (_,_) format = fun x -> !string_of_int x
let sprintf (f:(_,_) format) = f (fun s -> s) ""
let myformat:(_,_) format =
fun x -> (lit "expecting an int:\""++ int ++ lit "\"and a
string:\""++ string ++ lit "\";") x
let _ = sprintf myformat
(*
Mlton style folding....
The formats resulting from this solution are very terse. Type-checking is
very involved and cannot be abstracted easily.
The mechanics behind are explained on mlton's web page (http://mlton.org/Fold)
I believe this hack should be attribute to Stephen Weeks.
*)
let endf acc f = f acc
module Fold =
struct
let fold a f g = g a f
let step0 h a f = fold (h a) f
let step1 h a f b = fold (h b a) f
end
module Foldr =
struct
let foldr a f = Fold.fold f (fun g -> g a)
let step0 h = Fold.step0 (fun g x -> g (h x))
let step1 h = Fold.step1 (fun b g x -> g (h b x))
end
let (!) f = fun z -> Foldr.step1 (fun s k ((+),acc,stop) a -> k
((+),(acc + (f a) + s),stop)) z;;
let (<<) s = Foldr.foldr (fun (_,acc,stop) -> stop acc) (fun k init
stop (+) -> k ((+),init+s,stop))
let (>>) = endf
let sprintf f =
f (Buffer.create 17) (Buffer.contents) (fun b s -> Buffer.add_string b s;b)
let int k = !string_of_int k
let string k = !string_of_string k
let _ = sprintf ((<<)"expecting an int:\""int"\"and a string:\""string"\";"(>>))
(*
Rectypes
This one is by me... it requires -rectypes and is a lot more useless than the
previous ones... I just felt like putting it down anyways
*)
type ('a,'b) acc = (?peak:('b -> unit) -> 'a -> ('a,'b) acc)
let makeAcc init (+) : (_,_) acc =
let rec aux acc ?peak =
(match peak with
| Some f -> f acc
| None -> ());
fun v -> aux (acc+v)
in aux init
let (|>) x f = f x
let peak (acc:(_,'a) acc) : 'a =
let res = ref None in
let set v = res := Some v in
ignore (acc ~peak:set);
match !res with
| Some v -> v
| None -> assert false
let _ =
let sum = makeAcc 0 (+) in
sum 3 4 5 6 |> peak
Till
--
http://till-varoquaux.blogspot.com/
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2007-11-12 1:21 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-11-12 1:20 Folding in ML (was "OCaml's formatting libraries") Till Varoquaux
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).