Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the Scala type-programming analogy for the `this` keyword?

I'm trying to work my way into understanding type-programming in Scala, and I've found that most of what one needs to know about type programming has an analogous counterpart in value programming as is reflected in the type-level programming wiki page. However, I've not found the analogy for the this key word or self-types. I suspect maybe it doesn't make sense to expect such a thing, but I thought I would ask.

For instance, I can write the following to represent Booleans as values at run time:

sealed trait BoolVal {
  def not:BoolVal
  def or(that:BoolVal):BoolVal
  def and(that:BoolVal) =
    (this.not or that.not).not
  def imp(that:BoolVal) =
    this.not or that
}
case object TrueVal extends BoolVal {
  override val not = FalseVal
  override def or(that:BoolVal) = TrueVal
}
case object FalseVal extends BoolVal {
  override val not = TrueVal
  override def or(that:BoolVal) = that
}

Here my and and imp are able to take advantage of the fact it doesn't matter if I am a false object or a true object to be defined correctly. My TrueVal and FalseVal objects can inherit the same code.

I can make the analogous type-level programming constructs, but I don't understand how to define And and Imp in my base trait.

sealed trait BoolType {
  type Not <: BoolType
  type Or[That <: BoolType] <: BoolType
  type And[That <: BoolType] = ???
  type Imp[That <: BoolType] = ???
}
sealed trait TrueType extends BoolType {
  override type Not = FalseType
  override type Or[That <: BoolType] = TrueType
}
sealed trait FalseType extends BoolType {
  override type Not = TrueType
  override type Or[That <: BoolType] = That
}

I can see where perhaps it doesn't make sense that my types inherit types, but the certainly inherit abstract types. Is there a way to define And and Impl in my BoolType, or do I have to define each in the respective TrueType and FalseType traits?

like image 669
joescii Avatar asked Feb 17 '14 04:02

joescii


2 Answers

You can always define an abstract type on your boolean base type as follows:

trait MyBool extends BoolType{
  type This <: BoolType
}

trait TrueType extends BoolType{
  type This = TrueType
}

and you should be good to go with a reference to yourself. Then you can use DeMorgan's Laws to do the following

 !(x && y) == (!x || !y)

Then by a double negative you can get you And condition going:

 !(!x || !y) == !!(x && y) == (x && y)
like image 80
wheaties Avatar answered Nov 15 '22 18:11

wheaties


I would suggest using self, example of your blog post adjusted:

sealed trait BoolType { self =>
  type Not <: BoolType
  type Or[That <: BoolType] <: BoolType
  type And[That <: BoolType] = self.type#Not#Or[That#Not]#Not
  type Imp[That <: BoolType] = self.type#Not#Or[That]
}
sealed trait TrueType extends BoolType {
  override type Not = FalseType
  override type Or[That <: BoolType] = TrueType
}
sealed trait FalseType extends BoolType {
  override type Not = TrueType
  override type Or[That <: BoolType] = That
}
like image 45
EECOLOR Avatar answered Nov 15 '22 16:11

EECOLOR