Reputation: 31
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
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
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