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
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.
--
Daniel C. Sobral
I travel to the future all the time.
> 2011/10/14 Oleg Zhurakousky <oleg.zhu...@gmail.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: mi...@milessabin.com
skype: milessabin
http://www.chuusai.com/
http://twitter.com/milessabin
--
Because it's more specific that nsub according the rules given in
6.26.3 of the spec.