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

Problems with self types

1 reply
Kris Nuttycombe
Joined: 2009-01-16,
User offline. Last seen 42 years 45 weeks ago.

Hi, all,

I'm trying to create a generic trait for intervals of continuous
values, with intervals of dates being the initial use case. I'm
attempting to use a recursive type definition so that I can identify
the type of the class that's mixing in the trait. My Interval trait
seems to compile fine, but I haven't been able to figure out how to
actually extend the trait to a concrete class that does what I want.
Can someone please help me figure out what I'm doing wrong?

Here is the interval trait:

trait Interval[T <: Ordered[T], U <: Interval[T,U]] {
this: U =>

def start : Option[T];
def end : Option[T];
def withStart(start: Option[T]) : U;
def withEnd(end: Option[T]) : U;

def startsBefore(other: U): Boolean = {
start.isEmpty || other.start.exists(_ > start.get)
}

def endsAfter(other: U): Boolean = {
end.isEmpty || other.end.exists(_ < end.get)
}

def disjoint(other: U): Boolean = {
end.flatMap(x => other.start.filter(_ > x)).
orElse(start.flatMap(x => other.end.filter(_ < x))).
isDefined
}

def intersect(other: U): Option[U] = {
if (disjoint(other)) {
None
} else if (startsBefore(other) && endsAfter(other)) {
Some(other)
} else if (startsBefore(other) && other.endsAfter(this)) {
Some(withEnd(other.start))
} else if (other.startsBefore(this) && endsAfter(other)) {
Some(withStart(other.end))
} else {
other.intersect(this);
}
}

def union(other: U): Either[U, (U, U)] = {
if (disjoint(other)) {
Right(this, other)
} else if (startsBefore(other) && endsAfter(other)) {
Left(this)
} else if (startsBefore(other) && other.endsAfter(this)) {
Left(withEnd(other.end))
} else if (other.startsBefore(this) && endsAfter(other)) {
Left(withStart(other.start))
} else {
other.union(this)
}
}
}

Here's what I'm trying to do with it. The SafeDateTime class is there
because Option doesn't extend java.lang.Comparable, and also because
while DateTime extends Comparable, it doesn't extend
Comparable:

import _root_.org.joda.time.DateTime;
import _root_.org.joda.time.ReadableInstant;

class SafeDateTime(val d: DateTime) extends Ordered[DateTime] {
def apply() = d;
override def compare(other: DateTime) = d.compareTo(other)
}

//does not compile
class DateTimeInterval(override val start: Option[SafeDateTime],
override val end: Option[SafeDateTime]) extends Interval[SafeDateTime,
DateTimeInterval] {
override def withStart(s: Option[SafeDateTime]): DateTimeInterval
= new DateTimeInterval(s, end);
override def withEnd(e: Option[SafeDateTime]): DateTimeInterval =
new DateTimeInterval(start, e);
}

The compilation error:
[WARNING] /home/knuttycombe/projects/nutsutil/src/main/scala/org/nuttycombe/util/DateTimeInterval.scala:15:
error: type arguments
[org.nuttycombe.util.SafeDateTime,org.nuttycombe.util.DateTimeInterval]
do not conform to trait Interval's type parameter bounds [T <:
Ordered[T],U <: org.nuttycombe.util.Interval[T,U]]
[WARNING] class DateTimeInterval(override val start:
Option[SafeDateTime], override val end: Option[SafeDateTime]) extends
Interval[SafeDateTime, DateTimeInterval] {
[WARNING]
^
[WARNING] one error found

Thanks for your help.

Kris

ewilligers
Joined: 2008-08-20,
User offline. Last seen 3 years 17 weeks ago.
Re: Problems with self types

Kris Nuttycombe wrote:

> trait Interval[T <: Ordered[T], ...] {

> Here's what I'm trying to do with it. The SafeDateTime class is there
> because Option doesn't extend java.lang.Comparable, and also because
> while DateTime extends Comparable, it doesn't extend
> Comparable:

> class SafeDateTime(val d: DateTime) extends Ordered[DateTime] {
> def apply() = d;
> override def compare(other: DateTime) = d.compareTo(other)
> }

SafeDateTime needs to extend Ordered[SafeDateTime] :-

class SafeDateTime(val d: DateTime) extends Ordered[SafeDateTime] {
def apply() = d;
override def compare(other: SafeDateTime) = d.compareTo(other.d)
}

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