Skip to content

Commit 7e37fa4

Browse files
committed
Fix hasUnknownMembers
Sometimes a computation of a superType will give NoType. Keeping with the spirit of unKnownMembers to say yes when in doubt, we should return true in this case. The change is necessary to make the recursive call of `develop` and the call to `flatMap` in `flatten` in typeclass-encoding2.scala typecheck.
1 parent 8912d97 commit 7e37fa4

File tree

2 files changed

+184
-60
lines changed

2 files changed

+184
-60
lines changed

compiler/src/dotty/tools/dotc/typer/ProtoTypes.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ object ProtoTypes {
105105
private def hasUnknownMembers(tp: Type)(implicit ctx: Context): Boolean = tp match {
106106
case tp: TypeVar => !tp.isInstantiated
107107
case tp: WildcardType => true
108+
case NoType => true
108109
case tp: TypeRef =>
109110
val sym = tp.symbol
110111
sym == defn.NothingClass ||

tests/pos/typeclass-encoding2.scala

Lines changed: 183 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,30 @@
11
/** A possible type class encoding for
22
3-
trait SemiGroup {
4-
def add(that: This): This
5-
}
6-
7-
trait Monoid extends SemiGroup
8-
common {
9-
def unit: This
10-
}
3+
trait SemiGroup extends TypeClass {
4+
def add(that: This): This
5+
}
116
12-
extension IntOps for Int : Monoid {
13-
def add(that: Int) = this + that
14-
}
15-
common {
16-
def unit = 0
17-
}
7+
trait Monoid extends SemiGroup
8+
common {
9+
def unit: This
10+
}
1811
19-
extension StringOps for String : Monoid {
20-
def add(that: Int) = this ++ that
21-
}
22-
common {
23-
def unit = ""
24-
}
12+
extension IntOps for Int : Monoid {
13+
def add(that: Int) = this + that
14+
}
15+
common {
16+
def unit = 0
17+
}
2518
26-
def sum[T: Monoid](xs: List[T]): T =
27-
(instance[T, Monoid].unit /: xs)(_ `add` _)
19+
extension StringOps for String : Monoid {
20+
def add(that: Int) = this ++ that
21+
}
22+
common {
23+
def unit = ""
24+
}
2825
26+
def sum[T: Monoid](xs: List[T]): T =
27+
(Monod.impl[T].unit /: xs)(_ `add` _)
2928
*/
3029
object runtime {
3130

@@ -40,6 +39,11 @@ object runtime {
4039
def inject(x: This): Instance { val common: self.type }
4140
}
4241

42+
trait TypeClassCompanion {
43+
type Impl[T] <: Extension[T, _]
44+
def impl[T](implicit ev: Impl[T]): Impl[T] = ev
45+
}
46+
4347
trait Extension[From, To <: TypeClass] extends TypeClassCommon {
4448
type This = From
4549
type Instance = To
@@ -54,12 +58,16 @@ import runtime._
5458
object semiGroups {
5559

5660
trait SemiGroup extends TypeClass {
61+
val common: SemiGroupCommon
5762
import common._
5863
def add(that: This): This
5964
}
6065
trait SemiGroupCommon extends TypeClassCommon {
6166
type Instance <: SemiGroup
6267
}
68+
object SemiGroup extends TypeClassCompanion {
69+
type Impl[T] = Extension[T, SemiGroup] with SemiGroupCommon
70+
}
6371

6472
trait Monoid extends SemiGroup {
6573
val common: MonoidCommon
@@ -69,6 +77,9 @@ object semiGroups {
6977
type Instance <: Monoid
7078
def unit: This
7179
}
80+
object Monoid extends TypeClassCompanion {
81+
type Impl[T] = Extension[T, Monoid] with MonoidCommon
82+
}
7283

7384
implicit object IntOps extends Extension[Int, Monoid] with MonoidCommon { self =>
7485
type This = Int
@@ -90,51 +101,51 @@ object semiGroups {
90101
}
91102
}
92103

93-
def sum[T](xs: List[T])(implicit $ev: Extension[T, Monoid] with MonoidCommon) =
94-
(implicitly[Extension[T, Monoid] with MonoidCommon].unit /: xs)((x, y) => x `add` y)
104+
def sum[T](xs: List[T])(implicit $ev: Monoid.Impl[T]) =
105+
(Monoid.impl[T].unit /: xs)((x, y) => x `add` y)
95106
}
96107

97108
/** Encoding for
98109
99-
trait Ord {
100-
def compareTo(that: This): Int
101-
def < (that: This) = compareTo(that) < 0
102-
def > (that: This) = compareTo(that) > 0
103-
}
104-
common {
105-
val minimum: This
106-
}
110+
trait Ord extends TypeClass {
111+
def compareTo(that: This): Int
112+
def < (that: This) = compareTo(that) < 0
113+
def > (that: This) = compareTo(that) > 0
114+
}
115+
common {
116+
val minimum: This
117+
}
107118
108-
extension IntOrd for Int : Ord {
109-
def compareTo(that: Int) =
110-
if (this < that) -1 else if (this > that) +1 else 0
111-
}
112-
common {
113-
val minimum = Int.MinValue
114-
}
119+
extension IntOrd for Int : Ord {
120+
def compareTo(that: Int) =
121+
if (this < that) -1 else if (this > that) +1 else 0
122+
}
123+
common {
124+
val minimum = Int.MinValue
125+
}
115126
116-
extension ListOrd[T : Ord] for List[T] : Ord {
117-
def compareTo(that: List[T]): Int = (this, that) match {
118-
case (Nil, Nil) => 0
119-
case (Nil, _) => -1
120-
case (_, Nil) => +1
121-
case (x :: xs, y :: ys) =>
122-
val fst = x.compareTo(y)
123-
if (fst != 0) fst else xs.compareTo(ys)
127+
extension ListOrd[T : Ord] for List[T] : Ord {
128+
def compareTo(that: List[T]): Int = (this, that) match {
129+
case (Nil, Nil) => 0
130+
case (Nil, _) => -1
131+
case (_, Nil) => +1
132+
case (x :: xs, y :: ys) =>
133+
val fst = x.compareTo(y)
134+
if (fst != 0) fst else xs.compareTo(ys)
135+
}
136+
}
137+
common {
138+
val minimum = Nil
124139
}
125-
}
126-
common {
127-
val minimum = Nil
128-
}
129140
130-
def min[T: Ord](x: T, y: T) = if (x < y) x else y
141+
def min[T: Ord](x: T, y: T) = if (x < y) x else y
131142
132-
def inf[T: Ord](xs: List[T]): T = (instance[T, Ord].minimum /: xs)(_ `min` _)
143+
def inf[T: Ord](xs: List[T]): T = (Ord.impl[T].minimum /: xs)(min)
133144
*/
134-
135145
object ord {
136146

137147
trait Ord extends TypeClass {
148+
val common: OrdCommon
138149
import common._
139150
def compareTo(that: This): Int
140151
def < (that: This) = compareTo(that) < 0
@@ -144,6 +155,9 @@ object ord {
144155
type Instance <: Ord
145156
def minimum: This
146157
}
158+
object Ord extends TypeClassCompanion {
159+
type Impl[T] = Extension[T, Ord] with OrdCommon
160+
}
147161

148162
implicit object IntOrd extends Extension[Int, Ord] with OrdCommon { self =>
149163
type This = Int
@@ -156,7 +170,7 @@ object ord {
156170
}
157171
}
158172

159-
class ListOrd[T](implicit ev: Extension[T, Ord] with OrdCommon)
173+
class ListOrd[T](implicit ev: Ord.Impl[T])
160174
extends Extension[List[T], Ord] with OrdCommon { self =>
161175
type This = List[T]
162176
type Instance = Ord
@@ -174,14 +188,123 @@ object ord {
174188
}
175189
}
176190

177-
implicit def listOrd[T](implicit ev: Extension[T, Ord] with OrdCommon): ListOrd[T] =
191+
implicit def listOrd[T](implicit ev: Ord.Impl[T]): ListOrd[T] =
178192
new ListOrd[T]
179193

180-
def min[T](x: T, y: T)(implicit ev: Extension[T, Ord] with OrdCommon): T =
194+
def min[T](x: T, y: T)(implicit ev: Ord.Impl[T]): T =
181195
if (x < y) x else y
182196

183-
def inf[T](xs: List[T])(implicit ev: Extension[T, Ord] with OrdCommon): T = {
184-
val smallest = implicitly[Extension[T, Ord] with OrdCommon].minimum
185-
(smallest /: xs)(min(_, _))
197+
def inf[T](xs: List[T])(implicit ev: Ord.Impl[T]): T = {
198+
val smallest = Ord.impl[T].minimum
199+
(smallest /: xs)(min)
200+
}
201+
}
202+
203+
/** Encoding for
204+
205+
trait Functor[A] extends TypeClass1 {
206+
def map[B](f: A => B): This[B]
207+
}
208+
common {
209+
def pure[A](x: A): This[A]
210+
}
211+
212+
// Generically, `pure[A]{.map(f)}^n`
213+
def develop[A, F[X] : Functor[X]](n: Int, f: A => A): F[A] =
214+
if (n == 0) Functor.impl[F].pure[A]
215+
else develop[A, F](n - 1, f).map(f)
216+
217+
trait Monad[A] extends Functor[A] {
218+
def flatMap[B](f: A => This[B]): This[B]
219+
def map[B](f: A => B) = this.flatMap(f.andThen(pure))
220+
}
221+
222+
extension ListMonad[T] for List[T] : Monad[T] {
223+
static def pure[A] = Nil
224+
225+
def flatMap[B](f: A => List[B]): List[B] = this match {
226+
case x :: xs => f(x) ++ xs.flatMap(f)
227+
case Nil => Nil
228+
}
229+
}
230+
231+
extension MonadFlatten[T[X]: Monad[X]] for T[T[A]] {
232+
def flatten: T[A] = this.flatMap(identity)
233+
}
234+
*/
235+
object runtime1 {
236+
237+
trait TypeClass1 {
238+
val common: TypeClassCommon1
239+
type This = common.This
240+
}
241+
242+
trait TypeClassCommon1 { self =>
243+
type This[X]
244+
type Instance[X] <: TypeClass1
245+
def inject[A](x: This[A]): Instance[A] { val common: self.type }
246+
}
247+
248+
trait TypeClassCompanion1 {
249+
type Impl[T[_]] <: Extension1[T, _]
250+
def impl[T[_]](implicit ev: Impl[T]): Impl[T] = ev
251+
}
252+
253+
trait Extension1[From[_], To[X] <: TypeClass1] extends TypeClassCommon1 {
254+
type This[X] = From[X]
255+
type Instance[X] = To[X]
256+
}
257+
258+
implicit def inject1[A, From[_]](x: From[A])
259+
(implicit ev: Extension1[From, _]): ev.Instance[A] { type This = From } =
260+
ev.inject(x)
261+
}
262+
import runtime1._
263+
264+
object functors {
265+
266+
trait Functor[A] extends TypeClass1 {
267+
val common: FunctorCommon
268+
import common._
269+
def map[B](f: A => B): This[B]
270+
}
271+
trait FunctorCommon extends TypeClassCommon1 {
272+
type Instance[X] <: Functor[X]
273+
def pure[A](x: A): This[A]
274+
}
275+
object Functor extends TypeClassCompanion1 {
276+
type Impl[T[_]] = Extension1[T, Functor] with FunctorCommon
277+
}
278+
279+
trait Monad[A] extends Functor[A] {
280+
val common: MonadCommon
281+
import common._
282+
def flatMap[B](f: A => This[B]): This[B]
283+
def map[B](f: A => B) = this.flatMap(f.andThen(common.pure))
284+
}
285+
trait MonadCommon extends FunctorCommon {
286+
type Instance[X] <: Monad[X]
287+
}
288+
object Monad extends TypeClassCompanion1 {
289+
type Impl[T[_]] = Extension1[T, Monad] with MonadCommon
290+
}
291+
292+
def develop[A, F[X]](n: Int, x: A, f: A => A)(implicit ev: Functor.Impl[F]): F[A] =
293+
if (n == 0) Functor.impl[F].pure(x)
294+
else develop(n - 1, x, f).map(f)
295+
296+
implicit object ListMonad extends Extension1[List, Monad] with MonadCommon { self =>
297+
type This[A] = List[A]
298+
type Instance = Monad
299+
def pure[A](x: A) = x :: Nil
300+
def inject[A]($this: List[A]) = new Monad[A] {
301+
val common: self.type = self
302+
def flatMap[B](f: A => List[B]): List[B] = $this.flatMap(f)
303+
}
304+
}
305+
306+
object MonadFlatten {
307+
def flatten[T[_], A]($this: T[T[A]])(implicit ev: Monad.Impl[T]): T[A] =
308+
$this.flatMap(identity )
186309
}
187310
}

0 commit comments

Comments
 (0)