class Cell[T](value: T) { var other: T = value } object Test { def g[T, U](x: T, y: U) = if (util.Random.nextBoolean) x else y def f1 = g(1f, "abc") def f2 = g(1: Byte, "abc") def f3 = g(f1, f2) /*** Inferred return types: def g[T, U](x: T, y: U): T|U def f1: Float|String def f2: Byte|String def f3: String|Float|Byte ***/ def main(args: Array[String]): Unit = { val x = new Cell(f3) x.other = 1f // ok ( Float <:< Byte|Float|String) x.other = (1: Byte) // ok ( Byte <:< Byte|Float|String) x.other = "def" // ok (String <:< Byte|Float|String) x.other = 1d // nope // a.scala:15: error: type mismatch; // found : Double(1.0) // required: Byte|Float|String // x.other = 1d // ^ } }
I. want. this.
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
How so? Currently, if I make a list like List(BigInt(5),"a",1.5f), type inference will infer the greatest common ancestor as the type for the List, while with union types it would be a List[BigInt|String|Float]. I think that's more descriptive of what the List contains than List[Any].
With def x(a: String|Int) you could probably do something like
a match {
case v: String =>v.length
case v: Int => v + v
}
if there's no cleanlier way of doing things.
With def x(a: String|Int) you could probably do something like
a match {
case v: String =>v.lengthcase v: Int => v + v
}
case v: Int => v + v
Best Regards Ka Ter
So, on a 'A|B' you can call only methods that are within A *and* B.
As we speak of methods the concrete method of either A or B is called. 'A|B' is only a dynamic type that masks the object's concrete type. Both methods have the same signature and therefore the same interface but can have different implementations and therefore also different results and side effects. But that is not a problem and not different from the current polymorphic system. Just think of overriding toString() in A and B. If you cast an object of type A to Any and if you call toString, the method of A is used and not the one of Any. With union types there would be no different behavior, but just a more specific supertype that lies between Any and A and B.
Another question is what to choice, method overloading or sum types?
--
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
As suggested, it's duck typing and a loss of type safety.
What's the missing step?
On Wed, Jun 12, 2013 at 11:03 AM, Lex Spoon <l...@lexspoon.org> wrote:
What's the missing step?
I wrote it last night in a bar; I didn't say it was going anywhere; I rarely get what I want even if I thought it was.
That said, motivations exist, but I'll have to let others elaborate.
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
Is there a clear explanation of what union types are supposed to help
with? To put a point on it, Scala has positioned itself as a language
intended for mainstream development. Is the feeling at Typesafe that
union types will help with that use case, or is it for furthering some
other aim such as research publications?
If you want, you can guess from which language I copied that.The type system is based on analysis of "best" or principal types. For every expression, a unique, most specific type may be determined, without the need to analyze the rest of the expression in which it appears. And all types used internally by the compiler are denotable - that is, they can be expressed within the language itself. What this means in practice is that the compiler always produces errors that humans can understand, even when working with complex generic types. The Ceylon compiler never produces error messages with mystifying non-denotable types like Java's
List<capture#3-of ?>
.
An integral part of this system of denotable principal types is first-class support for union and intersection types. ...
--
If you want, you can guess from which language I copied that.
It's not any more a loss of type safety than overriding a method is. Further, var a: Int|String cannot be assigned any type other than Int or String. It looks more typesafe to me than just having the greatest common ancestor used.
I think I might be able to guess correctly...
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
That contract is not type-safety though. It's just good design.
When you override a method, you are supposed to fulfil the contract of the method overridden. Given a method call, you can find all possible method declarations that may be called.
If two types just happen to have a method with the same signature, there is no common contract. And you never know whether two methods may be called from the same call.
An actor receives a message and acts on it, returning either a string or a throwable. This is pretty common for actors, and sadly the common return type is Any, which does not at all reflect that in reality the actor will return 1 of two types. The union type makes it clear what kind of responses you can expect from an actor.
Using the suggested & syntax I of course meant
PartialFunction[String, Int] & PartialFunction[Int,Int]
BR
John
PartialFunction[String, Int] | PartialFunction[Int,Int]or aSo is that aPartialFunction[String|Int,Int]
?On Wed, Jun 12, 2013 at 3:01 PM, Paul Phillips <pa...@improving.org> wrote:On Wed, Jun 12, 2013 at 8:53 AM, Mark Hammons <markeh...@gmail.com> wrote:
With def x(a: String|Int) you could probably do something like
a match {
case v: String =>v.lengthcase v: Int => v + v
}
Also, it's sealed.(a: String|Int|Double) match {
case v: String => v.lengthcase v: Int => v + v
}<console>:10: warning: match may not be exhaustive.It would fail on the following input: DoubleNot that I implemented that last night, but it's a few minutes work.
So, on a 'A|B' you can call only methods that are within A *and* B. If both, A and B, share a supertype (like Any or AnyVal), 'A|B' also contains the supertypes' methods as 'A|B' is a subtype of that supertype.
So, on a 'A|B' you can call only methods that are within A *and* B. If both, A and B, share a supertype (like Any or AnyVal), 'A|B' also contains the supertypes' methods as 'A|B' is a subtype of that supertype.
Right; and can it be associative (and commutative)?
Right; and can it be associative (and commutative)?
Me. Too.
Am Mittwoch, 12. Juni 2013 10:54:41 UTC+2 schrieb Simon Ochsenreither:I. want. this.
Please? :)
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
Hello,
I'm not sure I understand every one's position on this, so let's give an example. Would the following be legal or illegal?
class Employee { def fire = println("bye") }
class Missile { def fire = println("boom") }
val e = new Employee
val m = new Missile
val bigGuy = if(util.Random.nextBoolean) e else m
bigGuy.fire
If this is legal, I think it is way too dangerous.
If this is illegal, then the advantage of union over Either[A, B] seems marginal.
So, on a 'A|B' you can call only methods that are within A *and* B. If both, A and B, share a supertype (like Any or AnyVal), 'A|B' also contains the supertypes' methods as 'A|B' is a subtype of that supertype.
On Wednesday, June 12, 2013 3:37:06 PM UTC-7, Oliver Ruebenacker wrote:
Hello,
I'm not sure I understand every one's position on this, so let's give an example. Would the following be legal or illegal?
class Employee { def fire = println("bye") }
class Missile { def fire = println("boom") }
val e = new Employee
val m = new Missile
val bigGuy = if(util.Random.nextBoolean) e else m
bigGuy.fire
If this is legal, I think it is way too dangerous.
If this is illegal, then the advantage of union over Either[A, B] seems marginal.
This has been answered. There is no duck typing (aside from no discussion with respect to how unions of duck typing types behaves. quack.). Only methods on common parents qualify -- the common (perhaps virtual) super type of the two.
Here is the quote:
---------------------------------------
On Wednesday, June 12, 2013 9:47:00 AM UTC-7, Paul Phillips wrote:
On Wed, Jun 12, 2013 at 9:04 AM, Ka Ter <ter....@googlemail.com> wrote:
So, on a 'A|B' you can call only methods that are within A *and* B. If both, A and B, share a supertype (like Any or AnyVal), 'A|B' also contains the supertypes' methods as 'A|B' is a subtype of that supertype.-----------------------------------------This is how it will be implemented; I didn't do it last night only because the relevant compiler code is a nightmare.
One huge non-syntactic benefit over Either or similar is that there is (potentially) no unnecessary boxing. Creating objects on the heap purely so the runtime can do what the compiler could infer is a waste.
It also seems like it would play well with the other discussion on implicit type widening -- List(1, 2.0) becoming type List[Int|Double] is quite interesting.
Hello,On Wed, Jun 12, 2013 at 7:36 PM, Scott Carey <scott...@gmail.com> wrote:
On Wednesday, June 12, 2013 3:37:06 PM UTC-7, Oliver Ruebenacker wrote:
Hello,
I'm not sure I understand every one's position on this, so let's give an example. Would the following be legal or illegal?
class Employee { def fire = println("bye") }
class Missile { def fire = println("boom") }
val e = new Employee
val m = new Missile
val bigGuy = if(util.Random.nextBoolean) e else m
bigGuy.fire
If this is legal, I think it is way too dangerous.
If this is illegal, then the advantage of union over Either[A, B] seems marginal.
This has been answered. There is no duck typing (aside from no discussion with respect to how unions of duck typing types behaves. quack.). Only methods on common parents qualify -- the common (perhaps virtual) super type of the two.
Here is the quote:
---------------------------------------
On Wednesday, June 12, 2013 9:47:00 AM UTC-7, Paul Phillips wrote:
On Wed, Jun 12, 2013 at 9:04 AM, Ka Ter <ter....@googlemail.com> wrote:
So, on a 'A|B' you can call only methods that are within A *and* B. If both, A and B, share a supertype (like Any or AnyVal), 'A|B' also contains the supertypes' methods as 'A|B' is a subtype of that supertype.-----------------------------------------This is how it will be implemented; I didn't do it last night only because the relevant compiler code is a nightmare.
I didn't think it means that, but I'm glad it does.
One huge non-syntactic benefit over Either or similar is that there is (potentially) no unnecessary boxing. Creating objects on the heap purely so the runtime can do what the compiler could infer is a waste.
Can't we teach the compiler to better optimize Either? Or wouldn't it do that already?
It also seems like it would play well with the other discussion on implicit type widening -- List(1, 2.0) becoming type List[Int|Double] is quite interesting.
How about List[Number]? I wonder why Scala doesn't have a Number supertype for Int, Long, Double, Float, etc, especially since their APIs overlap greatly? You could do Number.toDouble, but you can't do (Int|Long).toDouble.
A simple approach won't work, because you can stuff a null into either side of Either, so unboxed you can't distinguish left from right if the value is null and A and B are both subclasses of AnyRef. Using null sentinel objects can work, at the expense of more branching in various places.
This is one reason why I would be excited to see some way to express a type that cannot be null. Unboxed, you could cast (or implicitly convert) between types that extend from A|B (where each cannot be null) without runtime cost. Boxed, or with specialized null sentinels per type, you must do more work at runtime.
--
It would be better if the compiler creates a virtual supertype 'String|Int' that has the intersection of attributes and methods of both types String and Int (see also Curry-Howard-Isomorphism). So, on a 'A|B' you can call only methods that are within A *and* B. If both, A and B, share a supertype (like Any or AnyVal), 'A|B' also contains the supertypes' methods as 'A|B' is a subtype of that supertype.
Best Regards Ka TerAm 12.06.2013 14:53, schrieb Mark Hammons:
With def x(a: String|Int) you could probably do something like
a match {
case v: String =>v.lengthcase v: Int => v + v
}
if there's no cleanlier way of doing things.
On Wednesday, June 12, 2013 08:36:20 AM Oliver Ruebenacker wrote:
Hello,
OK, no total loss of type safety. But it looks like a step towards duck-typing. Or what methods can you call on A|B?
Take care
Oliver
On Wed, Jun 12, 2013 at 8:26 AM, Mark Hammons <markeh...@gmail.com> wrote:
How so? Currently, if I make a list like List(BigInt(5),"a",1.5f), type inference will infer the greatest common ancestor as the type for the List, while with union types it would be a List[BigInt|String|Float]. I think that's more descriptive of what the List contains than List[Any].
On Wednesday, June 12, 2013 08:10:45 AM Oliver Ruebenacker wrote:
Hello,
Automatic typing plus union types looks to me, at first glance, like entire loss of type safety. Maybe I'll change my mind after another cup of coffee, but for now I'm scared.
If union types needed to be declared explicitly, then I guess it would be fine. I suppose then you could just use something like Either[A, B].
Take care
Oliver
On Wed, Jun 12, 2013 at 5:47 AM, Rich Oliver <rzi...@gmail.com> wrote:
This looks good! However what I most desire though is
1) to have proper enumerations
2) To be able to sub type Enumerations, Numerations and Strings
3) To be able to apply set operations on the basic types and their sub types.
Integer odd & (> 4 )
Double (> 2.0) | (< 4.0)
String (First character is 'd') & (is > 4 characters long)
On Wednesday, June 12, 2013 9:47:07 AM UTC+1, Paul Phillips wrote:https://gist.github.com/paulp/5763757
class Cell[T](value: T) {
var other: T = value
}
object Test {
def g[T, U](x: T, y: U) = if (util.Random.nextBoolean) x else y
def f1 = g(1f, "abc")
def f2 = g(1: Byte, "abc")
def f3 = g(f1, f2)
/*** Inferred return types:
def g[T, U](x: T, y: U): T|U
def f1: Float|String
def f2: Byte|String
def f3: String|Float|Byte
***/
def main(args: Array[String]): Unit = {
val x = new Cell(f3)
x.other = 1f // ok ( Float <:< Byte|Float|String)
x.other = (1: Byte) // ok ( Byte <:< Byte|Float|String)
x.other = "def" // ok (String <:< Byte|Float|String)
x.other = 1d // nope
// a.scala:15: error: type mismatch;
// found : Double(1.0)
// required: Byte|Float|String
// x.other = 1d
// ^
}
}
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
--
Head of Systems Biology Task Force at PanGenX (http://www.pangenx.com)
Any sufficiently advanced technology is indistinguishable from magic.
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
--
Head of Systems Biology Task Force at PanGenX (http://www.pangenx.com)
Any sufficiently advanced technology is indistinguishable from magic.
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
1. "a sane approach to generic type argument inference". From a user's
point of view, rather than a compiler implementer's, Scala is more
than fine on this front. In fact, I think Scala already tries too
hard; at some point the user should say what they mean.
2. "optional values (things which can be null)". Scala has optional
values. Scala also has null.
Hello,
When you override a method, you are supposed to fulfil the contract of the method overridden. Given a method call, you can find all possible method declarations that may be called.
If two types just happen to have a method with the same signature, there is no common contract. And you never know whether two methods may be called from the same call.
Take care
OliverOn Wed, Jun 12, 2013 at 11:55 AM, Mark Hammons <markeh...@gmail.com> wrote:
It's not any more a loss of type safety than overriding a method is. Further, var a: Int|String cannot be assigned any type other than Int or String. It looks more typesafe to me than just having the greatest common ancestor used.
On Wednesday, June 12, 2013 11:38:33 AM Oliver Ruebenacker wrote:
Hello,
Automatically deduced union types will allow you to substitute an object with one of an unrelated type, having a completely unrelated method called that just accidentally has the signature matching a call. If that is not loss of type safety, then I don't know what is.
Take care
OliverOn Wed, Jun 12, 2013 at 11:35 AM, Paul Phillips <pa...@improving.org> wrote:
On Wed, Jun 12, 2013 at 11:29 AM, Oliver Ruebenacker <cur...@gmail.com> wrote:
As suggested, it's duck typing and a loss of type safety.
It's funny how on twitter the people displaying the highest interest are all fervent type-safety lovers. I wonder how it happened.
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-language+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
--
Head of Systems Biology Task Force at PanGenX (http://www.pangenx.com)
Any sufficiently advanced technology is indistinguishable from magic.
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
A | B is isomorphic to Either[A, B]
The difference is that Either as class has some methods, like fold(left, right), which A | B as type doesn't.
Implicit classes could add extra methods
I built a “union type quiz”, freely inspired by the “programming language checklist”.¹
You can find it here: https://gist.github.com/soc/5776653
I think it might help to understand individual positions more clearly.
--
--
You received this message because you are subscribed to a topic in the Google Groups "scala-language" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/scala-language/J8LpYDmrOCg/unsubscribe.
To unsubscribe from this group and all its topics, send an email to scala-languag...@googlegroups.com.
because structural types are not more precise. They are _less_ precise because they are unsealed.9. What should be the inferred type ofif (true) Some(1) else None?(X) Option[Int]( ) Some[Int]|None( ) Other: ______________________________because Some[Int] | None has as LUB Option[Int] and that is exhausted by Some[Int] | None.10. What should be the inferred type ofif (true) Nil else List(1).asInstanceOf[::[Int]]?(X) List[Int]( ) Nil|::[Int]( ) Other: ______________________________because, again, Nil | ::[Int] is exhaustive.
11. When should a nominal type be preferred to a more precise union type?( ) Always( ) Never(X) Only if the element types enumerate all subclasses/subobjects of a sealed supertype( ) Other: ______________________________but there should be an easy way to downgrade to the LUB, and the compiler mightelect to only tell you about the LUB if the union type is messy, unless there is
a crucial distinction between the two in an error (for instance).12. When should a more precise structural type be preferred to a union type?( ) Always( ) Never(X) Only if the structural type is specified explicitly( ) Other: ______________________________
13. Given the following declarations ...trait T { def foo: Int }class A extends T { def foo: Int = ???; def bar: Int = ??? }class B extends T { def foo: Int = ???; def bar: Int = ???; def bippy: Int = ??? }... which members are allowed to be called on an instance aOrB of type A|B?[X] aOrB.toString[X] aOrB.foo[?] aOrB.bar[ ] aOrB.bippyYou should never lose the capabilities of the LUB. Whether the compiler should fill
in a pattern match for you is arguable. I would tend towards "yes", as it's hardly
the only performance gotcha in town.14. How will inference of union types interact with structural types?_Unions of structural types will just be unions___and the LUB will contain the intersection of ___
_members of those types._________________________so this will work (which it does not now):
scala> val x = new AnyRef { def foo: Int = 23; def bar = 24 }
x: AnyRef{def foo: Int; def bar: Int} = $anon$1@7aa3107c
scala> val y = new AnyRef { def foo: Int = 42; def baz = 41 }
y: AnyRef{def foo: Int; def baz: Int} = $anon$1@3d758b59
scala> (if (b) x else y).foo
<console>:12: error: value foo is not a member of Object
(if (b) x else y).foo15. Given the following definitions ...val x: AnyRef { def foo: Int } = nullval y: AnyRef { def foo: Int } = null... should it be allowed to call xOrY.foo?(X) Yes( ) No( ) Other: ______________________________16. Given the following definitions ...val x = new AnyRef { def foo: Int = 23}val y = new AnyRef { def foo: Int = 42}... should it be allowed to call xOrY.foo?(X) Yes( ) No( ) Other: ______________________________17. Will your choice from above break existing, valid code?( ) Yes( ) Yes, but it doesn't matter because: ______________________________(X) No, because: _They work now and still will________________________( ) Maybe?
Cool, and unusual. What are we supposed to do with it?
These are great questions!
10. What should be the inferred type of
if (true) Nil else List(1).asInstanceOf[::[Int]]?(X) List[Int]( ) Nil|::[Int]( ) Other: ______________________________because, again, Nil | ::[Int] is exhaustive.
On 14.06.2013 21:00, Rex Kerr wrote:
These are great questions!10. What should be the inferred type of
if (true) Nil else List(1).asInstanceOf[::[Int]]?(X) List[Int]( ) Nil|::[Int]( ) Other: ______________________________because, again, Nil | ::[Int] is exhaustive.
I thought that when DOT is implemented, the List and HList could sort-of be unified and the definition of :: could be
final case class ::[H, T](private var hd: T, private[scala] var tl: List[T]) extends List[H|T] { ... }
On 14.06.2013 21:42, Jan Vanek wrote:
On 14.06.2013 21:00, Rex Kerr wrote:
These are great questions!10. What should be the inferred type of
if (true) Nil else List(1).asInstanceOf[::[Int]]?(X) List[Int]( ) Nil|::[Int]( ) Other: ______________________________because, again, Nil | ::[Int] is exhaustive.
I thought that when DOT is implemented, the List and HList could sort-of be unified and the definition of :: could be
final case class ::[H, T](private var hd: T, private[scala] var tl: List[T]) extends List[H|T] { ... }
Here's a small example that I find jarring:
val output =
if (writable(settings.out))
settings.out
else
"/dev/null"
trait OutputSetting { def output: String }
val setting = new OutputSetting { def output = ... }
setting.Copy(output = ...)
BR,