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) -> boolinto 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 bothFooandBar, it will need to be visible to almost the entire codebase. A single function doesn't seem worth it.structureonly adds like 2 lines of code. It's not leaking any important implementation details either.