Scala infix type aliasing for >2 type parameters?
Asked Answered
S

2

9

I know in Scala, you can do type ===>[A, B] = Map[A, B] and then you can use infix notation to define def foo: String ===> Int which is same as saying def foo: Map[String, Int]. Is there any way to exploit this infix notation to create types with >2 arguments? For example, I want something like this:

type A ~> B ~~~> C to be an alias of say Map[A, Pair[B, C]] ?

Is there anyway I can write something line this:

type A to B -> C as alias for (A, B, C) type?

Shellishellie answered 28/4, 2014 at 6:22 Comment(0)
O
13

Interestingly operator precedence as defined for symbolic methods doesn't seem to hold for symbolic type aliases. Instead infix type aliases are always evaluated left associative:

type -[A,B] = Map[A,B] 
type /[A,B] = Map[A,B] // '/' has higher precedence than '-' as an operator
classOf[A - B / C] // Class[/[-[A,B],C]]
classOf[A / B - C] // Class[-[/[A,B],C]]

Unfortunately that means it will never be possible to do what you ask for without parentheses like this:

classOf[A - (B / C)] // Class[-[A,/[B,C]]

So the closest answer is the following:

type ~>[A,B] = Map[A,B]
type ~~~>[A,B] = Pair[A,B]
classOf[A ~> (B ~~~> C)] // Map[A,Pair[B,C]]

Ommitting the parentheses will only be possible if you use right associative aliases (ending with :)

type ~:[A,B] = Map[A,B]
type ~~~:[A,B] = Pair[A,B]
classOf[A ~: B ~~~: C] // Map[A,Pair[B,C]]

Again, unfortunately since all type aliases have the same precedence it is not possible to mix right and left associative aliases without parentheses.

Concerning the second part of your question: (A,B,C) is syntactic sugar for Tuple3[A,B,C] which is a type with three parameters. As infix types only take two parameters, I'm afraid that I believe there is no way to represent this type solely with infix types. You would always end up with nested two parameter types (e.g. (A,(B,C)) or ((A,B),C).

Ordway answered 6/5, 2014 at 9:15 Comment(3)
Great clarification. Didn't realise until your answer that the precedence was not the same!Essayist
Is it possible to achieve A as B ~> C to mean (A, B, C)?Shellishellie
@wrick: I don't believe this is possible on the type level. Infix types can only take two type parameters but (A,B,C) has three. Only ((A,B),C) or (A,(B,C)) are possible IMHO.Ordway
E
4

Short answer: no. A ~> B ~> C cannot mean Map[A, Pair[B, C]].

It could be made to mean Map[A, Map[B, C]], though, or Pair[A, Pair[B, C]].

Essayist answered 28/4, 2014 at 7:8 Comment(3)
What if I use two symbols e.g. A ~> B ==> C ?Shellishellie
That works, provided you get the precedence right for these infix “type constructors”, such that your example means Map[A, Pair[B, C]] and not Pair[Map[A, B], C]. Be sure to check section 6.12.3 of the Scala Language Specification.Essayist
A ~> B ~> C can not be made to mean Map[A,Map[B,C]]. Neither can anything without parentheses be made to mean Map[A,Pair[B,C]]. See my answer.Ordway

© 2022 - 2024 — McMap. All rights reserved.