sml - filtering values into two lists -
so i'm new sml , trying understand ins/out out of it. tried creating filter takes 2 parameters: function (that returns boolean), , list of values run against function. filter returns list of values return true against function.
code:
fun filter f [] = [] | filter f (x::xs) = if (f x) x::(filter f xs) else (filter f xs);
so works. i'm trying return tuple contains list of true values, , false. i'm stuck on conditional , can't see way. thoughts on how solve this?
code:
fun filter2 f [] = ([],[]) | filter2 f (x::xs) = if (f x) (x::(filter2 f xs), []) (* error *) else ([], x::(filter2 f xs)); (* error *)
so show way it, , better way (imo). 'better way' future reference when learn:
fun filter2 f [] = ([], []) | filter2 f (x::xs) = let fun ftuple f (x::xs) truelist falselist = if (f x) ftuple f xs (x::truelist) falselist else ftuple f xs truelist (x::falselist) | ftuple _ [] truelist falselist = (truelist, falselist) in ftuple f (x::xs) [] [] end;
the reason why yours not work because when call x::(filter2 f xs)
, compiler naively assuming building single list, doesn't assume tuple, stepping scope of function call. while think result type tuple of lists, compiler gets tunnel vision , thinks result type list. here better version in opinion, should function foldr
if curious, better employ technique since more readable, less verbose, , more importantly ... more predictable , robust:
fun filter2 f l = foldr (fn(x,xs) => if (f x) (x::(#1(xs)), #2(xs)) else (#1(xs), x::(#2(xs)))) ([],[]) l;
the reason why first example works because storing default empty lists accumulate copies of variables either fit condition, or not fit condition. however, have explicitly tell sml compiler make sure type rules agree. have make absolutely sure sml knows return type a tuple of lists. mistake in chain of command, , result in failure execute. hence, when working sml, study type inferences. second one, can see one-liner, leave research 1 on own, google foldr
, foldl
.
Comments
Post a Comment