Handle Optional as Applicative
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.Optional; | |
ExpandoMetaClass.enableGlobally() //you need this to add method through EMC to Closure. | |
// see: http://jira.codehaus.org/browse/GROOVY-3674 | |
Optional.metaClass.and = { Optional xs -> // Haskell's <*> (ap) | |
delegate.flatMap({Closure f-> | |
xs.map({x-> | |
if (f.parameterTypes.size() > 1) { | |
// In Haskell, if the number of supplied actural arguments is lesser | |
// then the number of expecting parameters(which is always 1), | |
// function is automatically partially applied, but Groovy don't. | |
// So we need call curry(partiall apply) explicitly. | |
return f.curry(x) | |
} | |
else { | |
return f.call(x) | |
} | |
})}) | |
} | |
Closure.metaClass.mod = { Optional xs -> // Haskell's <$> (fmap) | |
Optional.of(delegate) & xs | |
} | |
Closure.metaClass.applyOptional = { Object... args -> | |
def result = Optional.of(delegate) | |
args.each { | |
result = result & it | |
} | |
return result | |
} | |
Optional<String> arg1 = Optional.of("Abc") | |
Optional<String> arg2 = Optional.of("Def") | |
Optional<String> NULL = Optional.empty() | |
assert ({a,b -> a+' '+b} % arg1 & arg2) == Optional.of("Abc Def") | |
assert ({a,b -> a+' '+b} % arg1 & NULL) == NULL | |
assert ({a,b -> a+' '+b} % NULL & arg1) == NULL | |
assert ({a,b -> String.join(' ', a, b)} % arg1 & arg2) == Optional.of("Abc Def") | |
assert ({a,b -> String.join(' ', a, b)} % arg1 & NULL) == NULL | |
assert ({a,b -> String.join(' ', a, c)} % NULL & arg1) == NULL | |
Closure c1 = {a,b -> a+b} | |
Closure c2 = {a,b -> a.toUpperCase()+b.toLowerCase()} | |
Closure c3 = {a,b -> a.length() * b.length()} | |
assert (c1 % arg1 & arg2) == Optional.of("AbcDef") | |
assert (c1 % arg1 & NULL) == NULL | |
assert (c1 % NULL & NULL) == NULL | |
assert (c2 % arg1 & arg2) == Optional.of("ABCdef") | |
assert (c2 % NULL & arg2) == NULL | |
assert (c2 % NULL & NULL) == NULL | |
assert (c3 % arg1 & arg2) == Optional.of(9) | |
assert c1.applyOptional(arg1, arg2) == Optional.of("AbcDef") | |
assert c1.applyOptional(arg1, NULL) == NULL | |
assert c1.applyOptional(NULL, NULL) == NULL | |
assert c2.applyOptional(arg1, arg2) == Optional.of("ABCdef") | |
assert c2.applyOptional(NULL, arg2) == NULL | |
assert c2.applyOptional(NULL, NULL) == NULL | |
assert c3.applyOptional(arg1, arg2) == Optional.of(9) | |
assert ({a,b -> a+' '+b} % arg1 & arg2) == Optional.of("Abc Def") | |
assert ({a,b,c -> a+' '+b+' '+c} % arg1 & arg2 & arg1) == Optional.of("Abc Def Abc") | |
assert ({a,b,c,d -> a+' '+b+' '+c+' '+d} % arg1 & arg2 & arg1 & arg2) == Optional.of("Abc Def Abc Def") | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment