Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Achieving laziness and memoization

Laziness is a corner stone in the book Purely Functional Data Structures, but it is not clearly described how he obtains it, at least to me. I thought I only needed to write:

datatype 'a susp = $ of 'a
fun force ($x) = x
fun plus (x, y) = $case (x, y) of ($m, $n) => m + n

But then I get the error:

- use "ch4.sml";;
[opening ch4.sml]
ch4.sml:3.20 Error: syntax error: inserting  ORELSE
[unexpected exception: Compile]

uncaught exception Compile [Compile: "syntax error"]
raised at: ../compiler/Parse/main/smlfile.sml:19.24-19.46
../compiler/TopLevel/interact/evalloop.sml:45.54
../compiler/TopLevel/interact/evalloop.sml:306.20-306.23
../compiler/TopLevel/interact/interact.sml:65.13-65.16

I tried modifying the function to

fun plus (x, y) = $(print "Evaluating...\n"; force x + force y)

But calling it with plus ($4, $5) evaluated it and didn't memoize it because it returns $ 9 instead of $ plus(force $4, force $5) and it printed Evaluating... both times.

- plus ($4, $5);;
Evaluating...
val it = $ 9 : int susp
- plus ($4, $5);;
Evaluating...
val it = $ 9 : int susp

I'd also like to obtain the keyword lazy, but I'm not sure whether SML New Jersey supports this, whether it was implemented by Chris Okasaki, or that it's manually desugared. The keyword is highlighted in my editor but when writing

fun lazy plus ($x, $y) = $ (x + y)

I get that lazy is the function taking two parameters plus and ($x, $y) as given by the type:

val lazy = fn : 'a -> int susp * int susp -> int susp


My question boils down to How do I obtain laziness and memoization in SML New Jersey?

like image 352
Little Helper Avatar asked Dec 05 '25 15:12

Little Helper


1 Answers

You need to enable laziness and add some parentheses (the $ in the book has peculiar parsing rules):

Standard ML of New Jersey v110.83 [built: Thu May 31 09:04:19 2018]
- Control.lazysml := true;
[autoloading]
[ ... boring details ...] 
[autoloading done]
val it = () : unit
- open Lazy;
[autoloading]
[autoloading done]
opening Lazy

  datatype 'a susp = $ of 'a
- fun plus (x, y) = $(case (x, y) of ($m, $n) => m + n);
val plus = fn : int susp * int susp -> int susp
-  val x = plus($4, $5);
val x = $$ : int susp
- fun force ($x) = x;
val force = fn : 'a susp -> 'a
- force x;
val it = 9 : int
- fun lazy plus ($x, $y) = $ (x + y);
val plus = fn : int susp * int susp -> int susp
val plus_ = fn : int susp * int susp -> int

Note that this does not memoize plus.

like image 66
molbdnilo Avatar answered Dec 07 '25 18:12

molbdnilo