Search code examples
smlsmlnj

return string from given list with spaces between words - sml


I have to write a SML function that returns a sentence consisting of words separated by spaces in the given list. I have to use at least one of foldl/foldr/map functions.

This is what I wrote:

fun add_spaces nil = ""
  | add_spaces(x::xs) = foldr (fn (x,xs) => (add_spaces x)^" "^xs) x [xs];

add_spaces(["Testing","function","with","this","sentence"]);

But that function brings a reversed string (sentence this with function Testing). I read in the internet that can be solved by reversing list ([xs] in this case right?) but how can I do that?

Thank you


Solution

  • Your function add_spaces uses foldr in a beautifully convoluted but likely misunderstood way.

    A regular recursive function, which won't satisfy the criterion of using foldl/foldr/map, is,

    fun add_spaces [] = ""
      | add_spaces [s] = s
      | add_spaces (s::ss) = s ^ " " ^ add_spaces ss
    

    A similar function relying on folding for its recursion would follow a pattern,

    fun add_spaces [] = ""
      | add_spaces (s1::ss) = fold<l/r> (fn (s,res) => ...) s1 ss
    

    where ... explicitly does not refer to add_spaces. Thus, you have at least two instruments to guide the order in which your items arrive. One being the order in which you refer to s and res inside the anonymous function in the above template, and the other being your choice of foldl and foldr.

    Notice also that foldl and foldr will traverse the list from different directions; from the left and from the right, respectively. To illustrate the order, try and fold with something that results in side-effects and see which effects arrive first:

    - ​foldl (fn (s, _) => print (s^"\n")) () ["Hello", "World!"];
    Hello
    World!
    > val it = () : unit
    - ​foldr (fn (s, _) => print (s^"\n")) () ["Hello", "World!"];
    World!
    Hello