import scalaz.\/._
object Application extends App { val nums = Set(1,2,3) val _ = nums.foldLeft(right(0)) { (acc, i) => if (i < 0) left("negative number") // Error, found: String("negative number") required: Nothing else for (prevsum <- acc) yield (prevsum + i) } }
import scalaz.\/.import scalaz.\/._
object Application extends App { val nums = Set(1,2,3) val a = nums.flatMap[String \/ Int, Set[String \/ Int]](a => Set(right(a))) // Note required duplication of String \/ Int argument }
Therefore, it might be nice if possible to partially apply (either using _ or named arguments) type signature and let Scala take care of the rest.In the first example, one should then be able to write right[String, _](0) or right[A = String](0) , and for the second example one could write nums.flatMap[String \/ Int, _] or nums.flatMap[String \/ Int, Set[_]] or nums.flatMap[B = String \/ Int].I believe that this will strike a better balance than having to write everything explicitly, when Scalas automatic inference fails or produces the wrong result.All (constructive) feedback and ideas are welcome. If people are interested, I shall go forth and write an official SIP.
I think that its an interesting idea that is worth fleshing out. I’d favour use of _
, or maybe Predef.?
, as the signal to infer the type, rather than named type parameters, which would be a bigger change to the language.
Here’s a quick prototype of the change that shows that the impact on the typechecker might not be too large. The backticked underscore is a way to sneak a wildcard through the parser, and aren’t a serious suggestion for the user facing syntax.
scala> def test[A, B >: A]: (A, B) = ???; def x = test[Int, `_`]
test: [A, B >: A]=> (A, B)
x: (Int, Int)
scala> val nums = Set(1,2,3)
nums: scala.collection.immutable.Set[Int] = Set(1, 2, 3)
scala> def right[L, R](r: R): Either[L, R] = Right(r)
right: [L, R](r: R)Either[L,R]
scala> def left[L, R](l: L): Either[L, R] = Left(l)
left: [L, R](l: L)Either[L,R]
scala> nums.foldLeft(right[String, `_`](0))( (acc, i) => left("nope"))
res0: Either[String,Int] = Left(nope)
scala> nums.flatMap[Either[String, Int], `_`](a => Set(right(a)))
res1: scala.collection.immutable.Set[Either[String,Int]] = Set(Right(1), Right(2), Right(3))
Another proposal of Paul's was based on something like currying, so you could have a function that lets you write f[Int][String](x) out just f[Int](x). I think the simple way of implementing it was nested apply's without parentheses, like def apply[A] = { def apply[B](x: B) = null }
This would allow for the same shortcutting, without (a) overloading _ more, or (b) giving an identifier like ? special meaning to the compiler.
--
You received this message because you are subscribed to the Google Groups "scala-debate" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-debate...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Not sure yet. Maybe we'll want to reserve `?` so that T? would mean T
| Null. I'd also explore named type arguments as an alternative.
I would prefer not going down that route. Giving special syntax for nulls will encourage people to start using it more extensively.
Currently null pretty much doesn't exist in Scala, and I think that's going to change if we provide "first-class" syntax. (See procedure syntax.)
Regards,AS
So, for example, the signature of `System.getProperty` would become `def getProperty(key: String?): String?`, and that `?` would serve as a constant reminder that we need to explicitly handle these `null`s, probably with something like the `Option(...)`, or perhaps some more concise convenience methods.
Hi Simon,
I think the point here is not that it would encourage people to use nulls, but would handle them in an acceptably-concise way everywhere they exist that we can't do anything about them, e.g. Java APIs.Complementing this would be a new global assertion that non-? types like `String` and `List[Int]` could never be null (assigning `null` to them would be an error), and this would be an extremely valuable enhancement. `T` would coerce to `T?` for all `T`, but not the other way round, unless you import or define a "dangerous" implicit, presumably. We could have that implicit emit a warning, if we wanted.
So, for example, the signature of `System.getProperty` would become `def getProperty(key: String?): String?`, and that `?` would serve as a constant reminder that we need to explicitly handle these `null`s, probably with something like the `Option(...)`, or perhaps some more concise convenience methods.
So, would this *encourage* people to use nulls? The default for any type you write down would be not to support `null`s, so I don't see why people would voluntarily add a `?` to a type just to make it more inconvenient to use.
No, "?" would be a postfix operator). You'd write
ArrayList[String?]?
As to commonality of usage, note that T? would also be the new, more
efficient way to write Option[T]. So I expect it would be quite widely
used!
Very true, and that is where effect checking comes in. If null
dereference is an effect we can apply the normal effect scoping rules
to it.
No, "?" would be a postfix operator). You'd write
ArrayList[String?]?
I'm not sure I'm getting this. Whether one uses the ? or the |Null syntax doesn't change the issue that nullability can exist deeply nested in some generic structures, and it's extremely hard to get rid of it there.
As to commonality of usage, note that T? would also be the new, more
efficient way to write Option[T]. So I expect it would be quite widely
used!
Would we get similar operators for Either, Try, Validation etc.?
If not, my main concern about this is that having nicer syntax for T|Null/Option[T] means people will prefer using it even if Either, Try or Validation would be more appropriate.
If we look at languages which provide syntax sugar like the ? operator, we can see that alternatives like Either, Try, Validation stopped existing there.