I've seen this question but it doesn't help me because I'm writing functional code (Standard ML) and the answers there are heavily focused towards OOP (the OP is advised to use the Facade pattern, to use inheritance, etc -- answers that are not relevant to an SML programmer).
In two separate, largely unrelated modules, Foo
and Bar
, I need to accomplish the same task: given functions equal
and equals
with the signatures:
val equal: t * t -> bool
val equals: t list * t list -> bool
make two new functions with the following signatures:
val equal': t * t -> t option
val equals': t list * t list -> t list option
Here, t
stands for either Foo.t
or Bar.t
. The natural solution is to use a higher order function:
local
fun boolToOpt (comparison: ('a * 'a) -> bool) (left, right) =
if comparison (left, right) then
SOME left
else
NONE
in
val equal' = boolToOpt equal
val equals' = boolToOpt equals
end
I need to repeat exactly this code snippet in both modules.
Now, this is a tiny, minor implementation detail, and it would be a bad idea to let it be publicly visible from either Foo
or Bar
. At the same time, it seems too small -- and too tightly coupled to the two equal(s)
functions -- to be factored out in to a module of its own. Maybe in another language, the equals'
functionality would merit its own class, say, ComparisonDecorator
, that overrides equal(s)
to give me functions with the return type t option
, but that's not an option here.
I run in to situations like these at least once per day. Is there a sane way to avoid just copy+pasting here?
('a * 'a) -> bool
into a('a * 'a) -> 'a option
" doesn't have any semantic weight. And because of how the project is organized, in order to make a new module visible to bothFoo
andBar
, it will need to be visible to almost the entire codebase. A single function doesn't seem worth it. – Patrick Collins Sep 13 '14 at 9:16structure
only adds like 2 lines of code. It's not leaking any important implementation details either. – Doval Sep 15 '14 at 2:43