[MLton-commit] r6583
Vesa Karvonen
vesak at mlton.org
Tue Apr 8 15:52:10 PDT 2008
An example of using iterator functions translated from a Haskell example.
----------------------------------------------------------------------
A mltonlib/trunk/com/ssh/extended-basis/unstable/example/iter/countdown.mlb
A mltonlib/trunk/com/ssh/extended-basis/unstable/example/iter/countdown.sml
----------------------------------------------------------------------
Added: mltonlib/trunk/com/ssh/extended-basis/unstable/example/iter/countdown.mlb
===================================================================
--- mltonlib/trunk/com/ssh/extended-basis/unstable/example/iter/countdown.mlb 2008-04-08 20:20:15 UTC (rev 6582)
+++ mltonlib/trunk/com/ssh/extended-basis/unstable/example/iter/countdown.mlb 2008-04-08 22:52:09 UTC (rev 6583)
@@ -0,0 +1,17 @@
+(* Copyright (C) 2008 Vesa Karvonen
+ *
+ * This code is released under the MLton license, a BSD-style license.
+ * See the LICENSE file or http://mlton.org/License for details.
+ *)
+
+../../basis.mlb
+
+local
+ ann
+ "warnUnused true"
+ "sequenceNonUnit warn"
+ in
+ countdown.sml
+ end
+in
+end
Property changes on: mltonlib/trunk/com/ssh/extended-basis/unstable/example/iter/countdown.mlb
___________________________________________________________________
Name: svn:eol-style
+ native
Added: mltonlib/trunk/com/ssh/extended-basis/unstable/example/iter/countdown.sml
===================================================================
--- mltonlib/trunk/com/ssh/extended-basis/unstable/example/iter/countdown.sml 2008-04-08 20:20:15 UTC (rev 6582)
+++ mltonlib/trunk/com/ssh/extended-basis/unstable/example/iter/countdown.sml 2008-04-08 22:52:09 UTC (rev 6583)
@@ -0,0 +1,147 @@
+(* Copyright (C) 2008 Vesa Karvonen
+ *
+ * This code is released under the MLton license, a BSD-style license.
+ * See the LICENSE file or http://mlton.org/License for details.
+ *)
+
+(**
+ * This is a translation of the ``Countdown'' example from Chapter 11 of
+ * the book:
+ *
+ * Programming in Haskell
+ * by Graham Hutton
+ * Cambridge University Press
+ * ISBN 0-521-69269-5
+ * http://www.cs.nott.ac.uk/~gmh/book.html
+ *
+ * See the WWW site for the original Haskell code.
+ *
+ * The original Haskell code uses lazy lists. This translation uses
+ * iterators rather than lists. The translation is rather mechanical
+ * and the programs are structurally very similar.
+ *
+ * Unsurprisingly using iterators gives excellent performance. On a
+ * Pentium M laptop, compiled with MLton, the solvers using iterators run
+ * more than 3 times faster than GHC (6.6.1) compiled solvers using lazy
+ * lists. Note that it is more than likely that the same technique, using
+ * iterators rather than lazy lists, could be used to speed up the Haskell
+ * version.
+ *)
+
+(*** Expressions ***)
+
+datatype b = ADD | SUB | MUL | DIV
+
+fun valid ADD _ _ = true
+ | valid SUB x y = x > y
+ | valid MUL _ _ = true
+ | valid DIV x y = x mod y = 0
+
+fun apply ADD x y = x + y
+ | apply SUB x y = x - y
+ | apply MUL x y = x * y
+ | apply DIV x y = x div y
+
+datatype x = VAL of int | APP of b * x * x
+
+fun eval (VAL n) e = if n > 0 then e n else ()
+ | eval (APP (b, l, r)) e = eval l (fn l =>
+ eval r (fn r =>
+ if valid b l r then e (apply b l r) else ()))
+
+(*** Combinatorial functions ***)
+
+fun subs [] e = e [] : unit
+ | subs (x::xs) e = subs xs (fn ys => (e ys ; e (x::ys)))
+
+fun interleave x [] e = e [x] : unit
+ | interleave x (y::ys) e =
+ (e (x::y::ys) ; interleave x ys (fn ys => e (y::ys)))
+
+fun perms [] e = e [] : unit
+ | perms (x::xs) e = perms xs (fn p => interleave x p e)
+
+fun choices xs e = subs xs (fn s => perms s e)
+
+(*** Brute force solution ***)
+
+fun split [] _ = ()
+ | split [_] _ = ()
+ | split (x::xs) e = (split xs (fn (ls, rs) => e (x::ls, rs)) ; e ([x], xs))
+
+fun bops e = (e ADD ; e SUB ; e MUL ; e DIV) : unit
+
+fun combine l r e = bops (fn b => e (APP (b, l, r)))
+
+fun exprs [] _ = ()
+ | exprs [n] e = e (VAL n)
+ | exprs ns e =
+ split ns (fn (l, r) => exprs l (fn x => exprs r (fn y => combine x y e)))
+
+fun solutions ns n e = choices ns (fn ns' =>
+ exprs ns' (fn x =>
+ eval x (fn n' =>
+ if n' = n then e x else ())))
+
+(*** Combining generation and evaluation ***)
+
+fun combine' (l, x) (r, y) e =
+ bops (fn b => if valid b x y then e (APP (b, l, r), apply b x y) else ())
+
+fun results [] _ = ()
+ | results [n] e = if n > 0 then e (VAL n, n) else ()
+ | results ns e = split ns (fn (l, r) =>
+ results l (fn x =>
+ results r (fn y =>
+ combine' x y e)))
+
+fun solutions' ns n e =
+ choices ns (fn ns' => results ns' (fn (x, m) => if m = n then e x else ()))
+
+(*** Exploiting numeric properties ***)
+
+fun valid' ADD x y = x <= y
+ | valid' SUB x y = x > y
+ | valid' MUL x y = x <= y andalso 1 < x
+ | valid' DIV x y = y <> 1 andalso x mod y = 0
+
+fun combine'' (l, x) (r, y) e =
+ bops (fn b => if valid' b x y then e (APP (b, l, r), apply b x y) else ())
+
+fun results' [] _ = ()
+ | results' [n] e = if n > 0 then e (VAL n, n) else ()
+ | results' ns e = split ns (fn (l, r) =>
+ results' l (fn x =>
+ results' r (fn y =>
+ combine'' x y e)))
+
+fun solutions'' ns n e =
+ choices ns (fn ns' => results' ns' (fn (x, m) => if m = n then e x else ()))
+
+(*** Main Program ***)
+
+val bToString = fn ADD => "+" | SUB => "-" | MUL => "*" | DIV => "/"
+
+fun xToString (VAL i) = Int.toString i
+ | xToString (APP (b, l, r)) =
+ concat ["(", xToString l, " ", bToString b, " ", xToString r, ")"]
+
+fun s2i s =
+ case Int.fromString s
+ of NONE => fails ["Not a number: ", s]
+ | SOME i => if i <= 0 then fails ["Not a positive number: ", s] else i
+
+fun main solver =
+ fn s::n::ns => solver (List.map s2i (n::ns)) (s2i s) (println o xToString)
+ | _ => fail "Not enough arguments"
+
+val () =
+ (case CommandLine.arguments ()
+ of "-brute" :: args => main solutions args
+ | "-combined" :: args => main solutions' args
+ | "-exploit" :: args => main solutions'' args
+ | args => main solutions'' args)
+ handle e =>
+ (println (Exn.message e)
+ ; printlns ["Usage: ", OS.Path.file (CommandLine.name ()),
+ " [-brute | -combined | -exploit] solution number ..."])
Property changes on: mltonlib/trunk/com/ssh/extended-basis/unstable/example/iter/countdown.sml
___________________________________________________________________
Name: svn:eol-style
+ native
More information about the MLton-commit
mailing list