0

I have this function

fun exist p M = foldr( fn(x,y) => x orelse y ) false (map p M)

I need to write it using only the foldr function, but can only call foldr once. I'm confused on how I should handle this. Do i need to revise my anon function?

user2796815
  • 465
  • 2
  • 11
  • 18
  • Using `foldr` to define exist(s) will result in checking all elements of a list even though you could technically stop once you find the one element that turns the predicate true. That is: `foldr` will not make your function as lazy as it could be. – sshine Oct 04 '13 at 12:28

1 Answers1

3

Yes, you need to revise your anonymous function. You can call p inside it.

fun exist p M = foldr (fn (x, y) => y orelse (p x)) false M

map in your code transforms values to bool type. You can do that in anonymous function. Also, switching x and y in orelse will save you some machine time, since if value satisfying p was found, p won't be executed on the rest of M.

- fun exist p M = foldr (fn (x, y) => y orelse (p x)) false M;
val exist = fn : ('a -> bool) -> 'a list -> bool
- exist (fn e => e = 1) [2,3,4];
val it = false : bool
- exist (fn e => e = 1) [2,3,4,1,2,3,4];
val it = true : bool

foldr takes 3 arguments

  1. function to fold list. It takes tuple argument (x, y), where x is current value from list, y - value list have been folded to so far.
  2. Starting value. It will be passed as y to the first first argument function together with the last value of a list.
  3. List to fold. Each value (starting last) of this list will be passed to the first argument function as x.

foldr will call folding function for every element of passed list.

Calls to folding (called it anon here) function for exist (fn e => e = 1) [2,1,4]; call:

anon (4, false);                              // here `false` is the false passed to `foldr`; returns false
anon (1, false orelse (p 4));                 // (p 1) -> true; returns true
anon (2, (false orelse (p 4)) orelse (p 1));  // returns true becuase `true or (p 2)` is true
zaquest
  • 2,030
  • 17
  • 25
  • I'm kind of confused on how the whole anonymous function works in my original exist. So map will be called that will generate the list of boo-leans based on the predicate and list the user provides. Then foldr breaks down the list until it has a false value to start with. How is this value and the head of the list used in the anon function? – user2796815 Oct 03 '13 at 19:55
  • I guess my real confusion is after the arguments are fed into the anon function, how does everything get evaluated with the orelse statement – user2796815 Oct 03 '13 at 20:01
  • Hope this will be enough to explain `foldr` :-) – zaquest Oct 03 '13 at 20:11
  • So even if when (p 1) gets passed in, it still has to go through and check the rest of the values? – user2796815 Oct 03 '13 at 20:15
  • 1
    Yes, it will go through the rest of the values, but since `orelse` executes expression on the right only when expression on the left is `false` `p` won't be called on the rest of the values. – zaquest Oct 03 '13 at 20:20
  • Please accept answer if it answers your question. If it does not please, let me know why. Same applies to your other questions. – zaquest Oct 03 '13 at 20:47
  • 1
    The expression can also be simplified to `fun exist p = foldr (fn (x,y) => y orelse p(x)) false` since both the `exist` function and the `foldr` function expect a list `xs` as their last argument. – Edwin Dalorzo Oct 04 '13 at 13:27