I wrote the following code in SML with the NJ Compiler:
fun all_answers (f, xs) =
let
fun aux(accu, xs_left) =
case xs of
[] => SOME accu
| x::xs' => case f(x) of
NONE => NONE
| SOME y => aux(accu@y, xs')
in
aux([], xs)
end
It works well for this tests:
val testAll1 = all_answers ((fn x => if x = 1 then SOME [x] else NONE), []) = SOME []
val testAll2 = all_answers ((fn x => if x = 1 then SOME [x] else NONE), [2,3,4,5,6,7]) = NONE
However, something weird happens with this test:
val testAll3 = all_answers ((fn x => if x = 1 then SOME [x] else NONE), [1]) = SOME [1]
After running the program, the terminal goes on forever.
I defined the tail recursion and used the pattern-match with xs'
to reach the tail.
Moreover, I defined the base case to end the recursion so that if xs
is []
then the auxiliary function returns SOME accumulator
Can anybody help me?
Thanks in advance.
As @kopecs pointed out, this is caused by
case xs of
when you wantcase xs_left of
.Here is a cleaned up (whitespace, naming) version of your function:
There are at least two things you could do to simplify the way this function is made. (1) Perform the
case xs of
inside the function pattern rather than in a nested case-of. (2) Remove the inneraux
function and simply do the recursion in the outer function, at the expense of some tail-recursionThe first simplification might look like:
And the second might look like:
This shows a pattern: Whenever you have
then you have a programming pattern that could be abstracted out with a function.
There is already a standard library function that is made for this called
Option.map
, so you could write:Try and play around with this function in the REPL:
Taking this in another direction, rather than an inner function:
This style is more Haskell-like because it follows a monadic design pattern.