This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Enforcing that the function returns something (other than Unit)

9 replies
Oleg Zhurakousky
Joined: 2011-10-14,
User offline. Last seen 42 years 45 weeks ago.
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

dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
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.

vpatryshev
Joined: 2009-02-16,
User offline. Last seen 1 year 24 weeks ago.
Re: Enforcing that the function returns something (other than U
The question is, what's so special about Unit.

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:
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


Sebastien Bocq
Joined: 2008-12-18,
User offline. Last seen 42 years 45 weeks ago.
Re: Enforcing that the function returns something (other than U


2011/10/14 Oleg Zhurakousky <oleg [dot] zhurakousky [at] gmail [dot] com>
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


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

milessabin
Joined: 2008-08-11,
User offline. Last seen 33 weeks 3 days ago.
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

ichoran
Joined: 2009-08-14,
User offline. Last seen 2 years 3 weeks ago.
Re: Enforcing that the function returns something (other than U
Very clever!  I'd never thought to use ambiguity that way.
  --Rex

On Sat, Oct 15, 2011 at 2:42 PM, Miles Sabin <miles [at] milessabin [dot] com> wrote:
On Fri, Oct 14, 2011 at 9:59 AM, Sébastien Bocq
<sebastien [dot] bocq [at] gmail [dot] com> wrote:

> 2011/10/14 Oleg Zhurakousky <oleg [dot] zhurakousky [at] gmail [dot] com>
>>
>> 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

Sebastien Bocq
Joined: 2008-12-18,
User offline. Last seen 42 years 45 weeks ago.
Re: Enforcing that the function returns something (other than U


2011/10/15 Miles Sabin <miles [at] milessabin [dot] com>
On Fri, Oct 14, 2011 at 9:59 AM, Sébastien Bocq
<sebastien [dot] bocq [at] gmail [dot] com> wrote:

> 2011/10/14 Oleg Zhurakousky <oleg [dot] zhurakousky [at] gmail [dot] com>
>>
>> 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


That's neat indeed!

Why is it called ambiguity? And why do you need two times the the same implicit (nsubAmbig1, nsubAmbig2)?
--
Sébastien
Sebastien Bocq
Joined: 2008-12-18,
User offline. Last seen 42 years 45 weeks ago.
Re: Enforcing that the function returns something (other than U


2011/10/15 Sébastien Bocq <sebastien [dot] bocq [at] gmail [dot] com>


2011/10/15 Miles Sabin <miles [at] milessabin [dot] com>
On Fri, Oct 14, 2011 at 9:59 AM, Sébastien Bocq
<sebastien [dot] bocq [at] gmail [dot] com> wrote:

> 2011/10/14 Oleg Zhurakousky <oleg [dot] zhurakousky [at] gmail [dot] com>
>>
>> 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


That's neat indeed!

Why is it called ambiguity? And why do you need two times the the same implicit (nsubAmbig1, nsubAmbig2)?
--
Sébastien

Never mind, I got it. Even more clever than what I thought :)

Cheers,
Sébastien
dcsobral
Joined: 2009-04-23,
User offline. Last seen 38 weeks 5 days ago.
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
>

milessabin
Joined: 2008-08-11,
User offline. Last seen 33 weeks 3 days ago.
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

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland