简体   繁体   中英

How do I simplify this transitive application in Scala

For a given function call f, with arguments a, b, and c, that calls function g using functions h and i to build the arguments, I can say:

f(a)(b)(c) = g( h(a)(b)(c), i(a)(b)(c) )

I know that I can create a function such that:

g'(h,i)(a)(b)(c) = g(h(a)(b)(c), i(a)(b)(c))

so that f can be

f = g'(h,i)

and thusly applying f(a)(b)(c) will yield the desired result.

I can brute force this from (where f becomes build):

def build(a: String)(b: String)(c: String) =
  Message(convA(a)(b)(c), convB(a)(b)(c))

to (given that h and i aren't important to be arguments, maybe this is where the disconnect is):

def gDash = {
  a:String => b: String => c: String => Message(convA(a)(b)(c), convB(a)(b)(c))
}

def build = a:String => b:String => c:String => gDash(a,b,c)

but I still have to specify the entire typing for (a,b,c). But I've gone from something that should be more complex and fragile to something simpler, but the implementation is actually a bigger mess! Is there a way to simplify this that doesn't require all this?

If I tupleize the arguments so that:

def gDash = implicit composite:(String,String,String) => Message(convA, convB)

def convA(composite: s) => ...
def convB(composite: s) => ...

def f(a: String)(b: String)(c: String) = gDash((a,b,c))

I'm not sure that's actually better, I feel like I'm missing something.

Methods require you to be explicit with parameters. Tuples can have type aliases assigned to them, which can help with the excess typing:

type S3 = (String, String, String)

And you can go back and forth between functions (A, B) => C and A => B => C with curried and Function.uncurried .

These give you the tools that you need to make more compact representations of your functions. For example, if you want something called build that has form String => String => String => Whatever , you could

val build = ((abc: S3) => Message(convA(abc), convB(abc)).curried

and then if you want to write gDash in place of Message you could do something like

def dash[A,B,C,D,E](g: (A,B) => C)(h: E=>A, i: E=>B): E => C = 
  (e: E) => g(h(e),i(e))

and then uncurry on the way in if you want E to actually be three separate string parameters.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM