- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Enforcing that the function returns something (other than Unit)
So in Java i can quickly determine if a method returns something or not by simply looking at its signature.In Scala we have Unit which is often mistaken for a Void since it is used in places equivalent to Java void. Anyway, here is my dilemma. For example; if I want to provide a function signature that ensures that the function returns Boolean I can do this:
def foo(function: String => Boolean)
now bar.foo{m => 4 < 3} - will work fine but bar.foo{m => 4} will not. Perfect.
But how do I structure the signature of the function to make sure that the following is legal bar.foo{m => m} or bar.foo{m => m.toString()} etc., but NOT bar.foo{m => println("4")}
In other words I want to enforce that the provided function code returns something (at least from its structure) - non-Unit
Cheers
Oleg










Re: Enforcing that the function returns something (other than U
2011/10/14 Oleg Zhurakousky <oleg [dot] zhurakousky [at] gmail [dot] com>
Just came up with this. It might prove hackish with usage but seems you can use type tags [1] and implicit to implement a (very) poor man's effect system.
scala> type Tagged[U] = { type Tag = U }
defined type alias Tagged
scala> type @@[T, U] = T with Tagged[U]
defined type alias $at$at
scala> type NotUnit = {}
defined type alias NotUnit
scala> implicit def tagBool(b:Boolean):Boolean @@ NotUnit = b.asInstanceOf[Boolean @@ NotUnit]
tagBool: (b: Boolean)@@[Boolean,NotUnit]
scala> implicit def tagAnyRef[T <: AnyRef](t:T):T @@ NotUnit = t.asInstanceOf[T @@ NotUnit]
tagAnyRef: [T <: AnyRef](t: T)@@[T,NotUnit]
scala> def m[A](f:String => A @@ NotUnit):A = f("hi!")
m: [A](f: String => @@[A,NotUnit])A
scala> m(_ == "hi!")
res6: Boolean = true
scala> m(println(_))
<console>:22: error: type mismatch;
found : Unit
required: @@[?,NotUnit]
m(println(_))
^
--
Sébastien
[1] https://gist.github.com/89c9b47a91017973a35f
Re: Enforcing that the function returns something (other than U
On Fri, Oct 14, 2011 at 9:59 AM, Sébastien Bocq
wrote:
> 2011/10/14 Oleg Zhurakousky
>>
>> So in Java i can quickly determine if a method returns something or not by
>> simply looking at its signature.
>> In Scala we have Unit which is often mistaken for a Void since it is used
>> in places equivalent to Java void. Anyway, here is my dilemma. For example;
>> if I want to provide a function signature that ensures that the function
>> returns Boolean I can do this:
>>
>> def foo(function: String => Boolean)
>>
>> now bar.foo{m => 4 < 3} - will work fine but bar.foo{m => 4} will not.
>> Perfect.
>>
>> But how do I structure the signature of the function to make sure that the
>> following is legal bar.foo{m => m} or bar.foo{m => m.toString()} etc., but
>> NOT bar.foo{m => println("4")}
>>
>> In other words I want to enforce that the provided function code returns
>> something (at least from its structure) - non-Unit
>
> Just came up with this. It might prove hackish with usage but seems you can
> use type tags [1] and implicit to implement a (very) poor man's effect
> system.
That's probably not the best way to approach it. Try this instead,
https://gist.github.com/c9f8befa932d98dcc7a4
// Encoding for "A is not a subtype of B"
trait <:!<[A, B]
// Uses ambiguity to rule out the cases we're trying to exclude
implicit def nsub[A, B] : A <:!< B = null
implicit def nsubAmbig1[A, B >: A] : A <:!< B = null
implicit def nsubAmbig2[A, B >: A] : A <:!< B = null
// Type alias for context bound
type |¬|[T] = {
type λ[U] = U <:!< T
}
def foo[T, R : |¬|[Unit]#λ](t : T)(f : T => R) = f(t)
foo(23)(_ + 1) // OK
foo(23)(println) // Doesn't compile
Cheers,
Miles
Re: Enforcing that the function returns something (other than U
Why does nsubAmbig take precedence over nsub?
On Sat, Oct 15, 2011 at 15:42, Miles Sabin wrote:
> On Fri, Oct 14, 2011 at 9:59 AM, Sébastien Bocq
> wrote:
>
>> 2011/10/14 Oleg Zhurakousky
>>>
>>> So in Java i can quickly determine if a method returns something or not by
>>> simply looking at its signature.
>>> In Scala we have Unit which is often mistaken for a Void since it is used
>>> in places equivalent to Java void. Anyway, here is my dilemma. For example;
>>> if I want to provide a function signature that ensures that the function
>>> returns Boolean I can do this:
>>>
>>> def foo(function: String => Boolean)
>>>
>>> now bar.foo{m => 4 < 3} - will work fine but bar.foo{m => 4} will not.
>>> Perfect.
>>>
>>> But how do I structure the signature of the function to make sure that the
>>> following is legal bar.foo{m => m} or bar.foo{m => m.toString()} etc., but
>>> NOT bar.foo{m => println("4")}
>>>
>>> In other words I want to enforce that the provided function code returns
>>> something (at least from its structure) - non-Unit
>>
>> Just came up with this. It might prove hackish with usage but seems you can
>> use type tags [1] and implicit to implement a (very) poor man's effect
>> system.
>
> That's probably not the best way to approach it. Try this instead,
>
> https://gist.github.com/c9f8befa932d98dcc7a4
>
> // Encoding for "A is not a subtype of B"
> trait <:!<[A, B]
>
> // Uses ambiguity to rule out the cases we're trying to exclude
> implicit def nsub[A, B] : A <:!< B = null
> implicit def nsubAmbig1[A, B >: A] : A <:!< B = null
> implicit def nsubAmbig2[A, B >: A] : A <:!< B = null
>
> // Type alias for context bound
> type |¬|[T] = {
> type λ[U] = U <:!< T
> }
>
> def foo[T, R : |¬|[Unit]#λ](t : T)(f : T => R) = f(t)
>
> foo(23)(_ + 1) // OK
> foo(23)(println) // Doesn't compile
>
> Cheers,
>
>
> Miles
>
> --
> Miles Sabin
> tel: +44 7813 944 528
> gtalk: miles [at] milessabin [dot] com
> skype: milessabin
> http://www.chuusai.com/
> http://twitter.com/milessabin
>
Re: Enforcing that the function returns something (other than U
On Sun, Oct 16, 2011 at 1:34 AM, Daniel Sobral wrote:
> Why does nsubAmbig take precedence over nsub?
Because it's more specific that nsub according the rules given in
6.26.3 of the spec.
Cheers,
Miles
Re: Enforcing that the function returns something (other than U
2011/10/15 Miles Sabin <miles [at] milessabin [dot] com>
That's neat indeed!
Why is it called ambiguity? And why do you need two times the the same implicit (nsubAmbig1, nsubAmbig2)?
--
Sébastien
Re: Enforcing that the function returns something (other than U
2011/10/15 Sébastien Bocq <sebastien [dot] bocq [at] gmail [dot] com>
Never mind, I got it. Even more clever than what I thought :)
Cheers,
Sébastien
Re: Enforcing that the function returns something (other than U
--Rex
On Sat, Oct 15, 2011 at 2:42 PM, Miles Sabin <miles [at] milessabin [dot] com> wrote:
Re: Enforcing that the function returns something (other than U
The same question can be asked about any other type: specify a signature that excludes T or its supertypes. There was recently a posting where negation was expressed via implication, like T => Void... I wonder...
Thanks,
-Vlad
On Thu, Oct 13, 2011 at 7:37 PM, Oleg Zhurakousky <oleg [dot] zhurakousky [at] gmail [dot] com> wrote:
Re: Enforcing that the function returns something (other than U
On Thu, Oct 13, 2011 at 23:37, Oleg Zhurakousky
wrote:
> So in Java i can quickly determine if a method returns something or not by
> simply looking at its signature.
> In Scala we have Unit which is often mistaken for a Void since it is used in
> places equivalent to Java void. Anyway, here is my dilemma. For example; if
> I want to provide a function signature that ensures that the function
> returns Boolean I can do this:
>
> def foo(function: String => Boolean)
>
> now bar.foo{m => 4 < 3} - will work fine but bar.foo{m => 4} will not.
> Perfect.
>
> But how do I structure the signature of the function to make sure that the
> following is legal bar.foo{m => m} or bar.foo{m => m.toString()} etc., but
> NOT bar.foo{m => println("4")}
>
> In other words I want to enforce that the provided function code returns
> something (at least from its structure) - non-Unit
That's something I never saw before. I'm a bit dubious if wanting a
generic T that is necessarily non-Unit is really useful -- there are
all sorts of places where returning Unit makes perfect sense.
Anyway, this problem is akin to the problem of not accepting Nothing,
though easier, since Unit isn't a subtype of anything but AnyVal and
Any. The way around that is usually by defining a type class such with
the acceptable types, but here you have a *non*-accepted type. The
solutions I saw were a much convoluted one by Miles Sabin, involving
representing types as logic clauses, and formulating the proper
axioms, and a simpler version where the type class is contra-variant,
and both an Any and a Nothing (or, in this case, a Unit) implicit is
made available, so that the case where both types are possible gives
an ambiguity error -- not exactly an informative message.