sml - A curry function that executes another function n times -


i'm solving old exam practice sml. 1 task found interesting was: write function repeat executes function signature 'a -> 'a.

i assumed requested function curry function , used o-operator:

fun repeat (1, f: 'a->'a) = f |   repeat (n, f: 'a->'a) = f o repeat (n-1, f); 

however, o operator not formally introduced in out course, , wonder how write without it?

not less verbose, in way, explicit, after, less verbose, explanations.

a curried function function getting single argument. if expression has more arguments, there many nested functions. first outer level function gets argument, , made of inner level function may it‑self made of inner function, , on. of inner level function may returned, not innermost, explained later (this kind of “partial evaluation”). inner function “specialized” arguments (formally, arguments bound in closure) of outer functions.

we know there @ least function argument f , integer argument counter. there needs argument seed also, invoke function f first time.

the order of nesting may arbitrary or specified. if not specified, prefer put least varying arguments on outer‑scope , varying in inner‑scope. here, is, least varying: f, counter seed.

this enough suggest beginning of template:

val repeat: ('a -> 'a) -> int -> 'a -> 'a =    fn f: 'a -> 'a =>       fn count: int =>          fn seed: 'a =>             … 

we implemented ('a -> 'a) -> int -> 'a part of signature. remains last -> 'a means 'a returned, , evaluated inner loop.

a loop may of form (in pseudo‑code):

val rec loop = fn =>    if condition-to-stop       return-something-or-`()`    else loop (i + 1) or (i - 1) 

if loop compute something, need argument acting accumulator, , return accumulator final result.

implementing loop , putting inside curried function template above, get:

val repeat: ('a -> 'a) -> int -> 'a -> 'a =    fn f: 'a -> 'a =>       fn count: int =>          fn seed: 'a =>             let                val rec loop = fn (counter, x) =>                   if counter <= 0 x                   else loop (counter - 1, f x)             in                loop (count, seed)             end 

do understand let … in … end construct here?

note guard on counter may use pattern did, sml's integer may negative (there no strict natural in sml), that's safer catch case too, if … … else instead of pattern matching. mileage may vary on point, that's not question's focus.

the same above, using fun instead of val rec:

fun repeat (f: 'a -> 'a) (count: int) (seed: 'a): 'a =    let       fun loop (counter, x) =          if counter <= 0 x          else loop (counter - 1, f x)    in       loop (count, seed)    end 

note repeat arguments not separated , (neither *). way write curried function using fun (on contrary, loop not curried). compare prior val version of same function. if no type specified , names, parenthesis can omitted.

a test function used f argument:

val appendanx = fn s: string => s ^ "x" 

the test:

val () = print (repeat appendanx 5 "blah:") 

curried function more abstract function getting tuple (which formally single argument, makes curried function too, that's story , bit cheating), outer function(s) may partially applied:

this partial application, leaving last argument, seed, unbound:

val repeatappendanxthreetimes = repeat appendanx 3 

then function may applied specifiying seed:

val () = print (repeatappendanxthreetimes "blah:") 

similarly, both counter , seed may left free:

val repeatappendanx = repeat appendanx val () = print (repeatappendanx 4 "blah:") 

another way of defining repeatappendanxthreetimes. compare other definition above:

val repeatappendanxthreetimes = repeatappendanx 3 val () = print (repeatappendanxthreetimes "blah:") 

Comments

Popular posts from this blog

php - Submit Form Data without Reloading page -

linux - Rails running on virtual machine in Windows -

php - $params->set Array between square bracket -