Siwei Wang
Siwei Wang

Reputation: 31

can foldl in sml process the elements in a string list and return another list?

If not, what should I do if I want to both modify elements in the list with a pre-defined function and return a list in the end with a single line of code?

For example: fun upperClass is the pre-defined function string -> string that make all characters in string upperclass and here I have a list ["a","b","c"] I want to write this function non-recursively and by using foldr return ["Ä","B","C"].

My previous attempt was foldr upperClass() [] ["a","b","c"], and it turns out a type mismatch as expected since normally I use OP:: for putting these elements back into the list.

Upvotes: 3

Views: 1300

Answers (2)

sshine
sshine

Reputation: 16145

What you describe is, as you comment yourself, map:

val uppercase = String.map Char.toUpper
val uppercaseMany = List.map uppercase

You should pick map when it most accurately describes what you're doing, since it conveys the intent of your code faster.

map does something more specific than foldl, since map can only always return a list with the same number of elements as its input, where each element has been transformed in exactly the same way and independent of the other functions (at least to the extent of map's own accord).

In fact, map is a special case of foldr since you can implement map using foldr but not the other way around:

fun map f = foldr (fn (x, xs) => f x :: xs) []

foldl and foldr can reduce a list of things to anything, e.g. a tree:

datatype 'a binaryTree = Leaf | Branch of 'a * 'a binaryTree * 'a binaryTree
fun insert (x, Leaf) = Branch (x, Leaf, Leaf)
  | insert (x, Branch (y, left, right)) =
    if x <= y then Branch (y, insert (x, left), right)
              else Branch (y, left, insert (x, right))
val listToTree = foldl insert Leaf

I picked foldl and foldr conveniently, but you can also express one using the other.

The idea of folding can work on any tree structure, not just lists. Here's a StackOverflow answer on how to fold binary trees, and here's a StackOverflow Q&A on Tail-recursion on trees.

Upvotes: 3

Tai
Tai

Reputation: 8004

Let's take a look at the documentation of foldl for list at http://sml-family.org/Basis/list.html#SIG:LIST.foldl:VAL

foldl f init [x1, x2, ..., xn]
   returns

   f(xn,...,f(x2, f(x1, init))...)

   or init if the list is empty. 

As you see, the final product of foldl is the product of the function f. If the return type of f is a list, you can get a list back. As you mentioned that you tried with ::, we know that this operator takes two elements, a type 'a element and a type 'a list and returns a type 'a list. foldl using (op ::) should also return a list.

Example:

foldl (op ::) [] [1,2,3,4]

returns

val it = [4,3,2,1] : int list

I think the challenge for you is to come up with a function f that returns a string list while processing the elements simultaneously. (Also, in the right order.)

Upvotes: 1

Related Questions