I'm trying to create a type
UnaryOrBinaryFunc
, that could conceptually be defined like this:
type A = ArgType => ReturnType
type B = (ArgType, ArgType) => ReturnType
type UnaryOrBinaryFunc = <Some code saying that UnaryOrBinaryFunc is either a A or a B>
in my code I tried to define UnaryOrBinaryFunc
as: type UnaryOrBinaryFunc = A with B
and it seemed to be acceptable for Eclipse, I sadly didn't find anything about using the with
keyword in association with the type
keyword on the Internet.
Now if you want a little bit of context on why I want to do that, I wrote something that looks like what I want to accomplish inside my project:
sealed trait Token
case object AND extends Token
case object NOT extends Token
type ArgType
type ReturnType
type A = ArgType => ReturnType
type B = (ArgType, ArgType) => ReturnType
type UnaryOrBinaryFunc = A with B
def f: A = ???
def g: B = ???
Map[TokenType, UnaryOrBinaryFunc] (
NOT -> f,
AND -> g
)
Notice that I used ???
for the definitions of f and g because I didn't want to bother defining them.
Now I get the following error, the same as in my project:
type mismatch; found : TypeDecl.A (which expands to) TypeDecl.ArgType ⇒
TypeDecl.ReturnType required: TypeDecl.UnaryOrBinaryFunc (which expands to)
TypeDecl.ArgType ⇒ TypeDecl.ReturnType with (TypeDecl.ArgType,
TypeDecl.ArgType) ⇒ TypeDecl.ReturnType
I really don't know how to do that, anyone has an idea of how I could define UnaryOrBinaryFunc
so I don't have to modify what is inside my Map
?
Many thanks.
To answer the question directly....
There are several ways of defining a coproduct in Scala.
The simplest, and probably the best with just two types is to use Either
:
type UnaryOrBinaryFunc =
Either[(ArgType, ArgType) => ReturnType, ArgType => ReturnType]
Map[TokenType, UnaryOrBinaryFunc] (
NOT -> Left(f),
AND -> Right(g)
)
You can write some aliases for Left and Right to make things more readable.
If you are using the Shapeless library, you can implement this with Coproducts as explained in this question:
type UnaryOrBinaryFunc =
(ArgType, ArgType) => ReturnType :+: ArgType => ReturnType
With plain scala, it's also possible to use a trick to create coproducts using implicits as shown here
sealed trait UnaryOrBinaryFunc
object UnaryOrBinaryFunc {
implicit object UnaryFunc extends UnaryOrBinaryFunc[ArgType => ReturnType]
implicit object BinaryFunc extends UnaryOrBinaryFunc[(ArgType, ArgType) => ReturnType]
}
Every function that processes UnaryOrBinaryFunc should take an implicit parameter of UnaryOrBinaryFunc as shown in the link given.
... However, I would question whether this complexity is necessary. To solve this problem I would do one of:
Define your functions to take List
s or Product
s, and switch on their lengths at runtime.
type UnaryOrBinaryFunc = Seq[ArgType] => ReturnType
Keep Unary and Binary functions separate, and make generic any functions that must process either.
val unaryFns = Map[TokenType, UnaryFunc] ( NOT -> f, ... ) val binaryFns = Map[TokenType, BinaryFunc] ( AND -> g, ... ) def processUnaryOrBinaryFn[T](fn: T) = { ... }
Which of all the above solutions is most appropriate will depend on what else you need to do :-).
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.