1

So I recently read the following blow post: http://www.chuusai.com/2011/06/09/scala-union-types-curry-howard/

And I really appreciated the approach! I am trying to make a function

def neq[A,B] = ...

Where neq[String, String] would not compile, but neq[String, Int] would. It seems like this should be possible but I do not think I deeply enough understand the ways in which we can use curry-howard to encode logic in types.

My failed attempt follows:

I thought that what we wanted was essentially an Xor. So we want

A and ~B or ~A and B

Since all we have in scala when doing implicit resolution are things like <:<, =:=, I figure I need an implies in there, since that is <:<. So we say:

~(A and ~B) => (~A and B)

But if I try to do the following this doesn't work:

implicitly[((String with (Int => Nothing)) => Nothing) <:< ((String => Nothing) with Int)]

Which makes sense as the types don't match up at all. So I really am not sure where to go! Would love any guidance.

leppie
  • 115,091
  • 17
  • 196
  • 297
A Question Asker
  • 3,339
  • 7
  • 31
  • 39

1 Answers1

2

As I understand you need to guaranty inequalities of A & B (correct me if I am wrong)

good solution (from Miles Sabin) in Shapeless library:

// Type inequalities
trait =:!=[A, B] 
def unexpected : Nothing = sys.error("Unexpected invocation")

implicit def neq[A, B] : A =:!= B = new =:!=[A, B] {}
implicit def neqAmbig1[A] : A =:!= A = unexpected
implicit def neqAmbig2[A] : A =:!= A = unexpected

And your neq method will looks like:

def neq[A,B](implicit ev : A =:!= B) = ...

Update:

xor:

A and ~B or ~A and B

by implicit resolution is not:

~(A and ~B) <:< (~A and B)

correct transformation is:

(A and ~B) <:!< (~A and B)
or:
(A and ~B) =:!= (~A and B)

than scala code:

type xor[A, B] = (A with ![B]) =:!= (![A] with B)

def neq[A,B](implicit ev : A xor B) = ...

and tests:

neq[Int, String]          // - ok
neq[String, Int]          // - ok
//neq[String, String]     // - compilation error
//neq[Int, Int]           // - compilation error

And after all, it can be simplified to:

A =:!= B
Yuriy
  • 2,772
  • 15
  • 22
  • Yuri -- thank you for your suggestion! I have seen things like this... this definitely gets the job done, however, it's more abusing a fact of the scala compiler than any mathematical relations. So while it definitely answers the question (thank you!), I'm curious if inequality is provable (or perhaps provably impossible?) at the type level? – A Question Asker Jul 11 '14 at 19:47