There are two code paths, comparing items by index [the "yes" condition] and then comparing them without regard to index [the "maybe" path]. Using recursion and a helper function [or two] allows both code paths to be followed:
val ls1 = ["duck", "goose", "swan", "gull"]
val ls2 = ["duck", "swan", "goose", "pigeon"]
fun checker (list1,list2) =
(* Zipping the two lists together creates
a list of pairs that can be searched
for "yes" values as the first part of the aux function.
It might be worth checking to see if
ListPair.zipEq is more suited to the
needs of a particular appliation. *)
let val zipped = ListPair.zip(list1, list2)
(* find_in_list is called if there is
no "yes" match. It recurses down
list2 with the string from list1
which did not return "yes". *)
fun find_in_list (x, xs) =
case xs
of [] => "no"
| x'::xs' =>
if x' = x
then "maybe"
else find_in_list (x, xs')
(* This function could be the main body
of checker, but instead it trampolines.
First it checks for "yes". Either appends
"yes" onto a recursive call to itself or
otherwise appends a call to find_in_list
onto a recursive call to itself.
The type checker wants an explicit type
for lop because the record is being accessed
with #1 and #2 *)
fun aux (lop : (string * string) list) =
case lop
of [] => []
| x'::xs' =>
if #1 (hd lop) = #2 (hd lop)
then "yes"::aux (tl lop)
else (find_in_list (#1 (hd lop), list2))::(aux (tl lop))
in aux(zipped) end
checker (ls1,ls2) (* returns ["yes", "maybe", "maybe", "no"] *)