Skip to content

Commit 9d4e528

Browse files
committed
More blue sky variants
1 parent 01de0b4 commit 9d4e528

File tree

4 files changed

+451
-15
lines changed

4 files changed

+451
-15
lines changed

tests/pending/pos/blueSkyExtensions.scala

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,15 @@ object blueSkyExtensions {
3131
}
3232

3333
extend Int : Monoid {
34-
def + (that: Int) = this + that
3534
static def unit = 0
35+
36+
def + (that: Int) = this + that
3637
}
3738

3839
extend String : Monoid {
39-
def + (that: Int) = this ++ that
4040
static def unit = ""
41+
42+
def + (that: Int) = this ++ that
4143
}
4244

4345
// Ord
@@ -62,24 +64,26 @@ object blueSkyExtensions {
6264
// Functor and Monad
6365

6466
trait Functor[A] {
65-
static def pure[A]: This[A]
67+
static type ThisC[A] <: Functor[A]
68+
static def pure[A]: ThisC[A]
6669

67-
def map[B](f: A => B): This[B]
70+
def map[B](f: A => B): ThisC[B]
6871
}
6972

7073
// Generically, `pure[A]{.map(f)}^n`
7174
def develop[A, F[X] : Functor[X]](n: Int, f: A => A): F[A] =
72-
if (n == 0) Functor.static[F].pure[A]
75+
if (n == 0) Functor.statics[F].pure[A]
7376
else develop[A, F](n - 1, f).map(f)
7477

7578
trait Monad[A] extends Functor[A] {
76-
static def pure[A]: This[A]
77-
78-
def flatMap[B](f: A => This[B]): This[B]
79+
static type ThisC[A] <: Monad[A]
80+
81+
def flatMap[B](f: A => ThisC[B]): ThisC[B]
7982
def map[B](f: A => B) = this.flatMap(f.andThen(pure))
8083
}
8184

8285
extend List[type T] : Monad[T] {
86+
static type ThisC[A] = List[A]
8387
static def pure[A] = Nil
8488

8589
def flatMap[B](f: A => List[B]): List[B] = this match {
@@ -95,33 +99,43 @@ object blueSkyExtensions {
9599
// Iterables
96100

97101
trait MonoIterable[A] {
98-
def filter(p: A => Boolean): This[A]
102+
static type ThisC[A] <: MonoIterable[A]
99103
static def empty: This[A]
100104
static def apply(xs: A*): This[A]
101-
}
102105

106+
def filter(p: A => Boolean): This[A]
107+
}
103108

104109
trait Iterable[A] extends MonoIterable[A] {
105-
def map[B](f: A => B): This[B]
106-
def flatMap[B](f: A => This[B]): This[B]
110+
static type ThisC[A] <: Iterable[A]
111+
112+
def map[B](f: A => B): ThisC[B]
113+
def flatMap[B](f: A => ThisC[B]): ThisC[B]
107114
}
108115

109116
extend String : MonoIterable[Char] {
110-
def filter(p: Char => Boolean): String = ...
111-
def map(f: Char => Char): String = ...
117+
static type ThisC[A] = String
112118
static def empty = ""
113119
static def apply(xs: A*) = xs.mkString
120+
121+
def filter(p: Char => Boolean): String = ...
122+
def map(f: Char => Char): String = ...
114123
}
115124

116125
extend String : Iterable[Char] {
126+
static type ThisC[A] = IndexedSeq[A]
127+
117128
def map[B](f: Char => B): IndexedSeq[B] = ...
118129
def flatMap[B](f: Char => IndexedSeq[B]): IndexedSeq[B] = ...
119130
}
120131

121132
extend List[type T] : Iterable[T] {
133+
static type ThisC[A] = List[A]
134+
static def empty = Nil
135+
static def apply(xs: A*) = (xs /: Nil)(_ :: _)
136+
122137
def filter(p: T => Boolean): List[T] = ...
123138
def map[B](f: T => B): List[B] = ...
124139
def flatMap[B](f: T => List[B]): List[B] = ...
125140
}
126-
127141
}
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
/** A blue sky sketch how one might evolve extensions to do type classes
2+
* without the current gap between functional and OO patterns.
3+
* Largely inspired by the way Rust does it.
4+
*
5+
* The main additions (to be worked out in detail) is a self type `This` and
6+
* a mechanism that a trait can abstract over companions of classes that implement it.
7+
* Companion types and methods are declared using `object` for now, just to
8+
* pick some familiar notation.
9+
*
10+
* Ideas about `This` (still vague at the moment)
11+
*
12+
* - Treat it as an additional abstract type in a trait, prefixed by the name of the trait
13+
* - An implementing (non-trait) class binds the `This` types of all the traits it implements
14+
* to itself.
15+
* - Later subclasses do not re-bind `This` types already bound by their superclasses.
16+
* (so in that sense, `This`-binding is like trait parameterization, the first implementing
17+
* classes determines the self type and the parameters of a trait)
18+
* - Paramerized classes have parameterized `This` types (e.g. Functor below).
19+
*/
20+
import Predef.{any2stringadd => _, _}
21+
object blueSkyExtensions {
22+
23+
// Semigroup and Monoid
24+
25+
trait SemiGroup {
26+
def add (that: This): This
27+
}
28+
29+
trait Monoid extends SemiGroup {
30+
static def unit: This
31+
}
32+
33+
extend Int : Monoid {
34+
def add (that: Int) = this + that
35+
static def unit = 0
36+
}
37+
38+
extend String : Monoid {
39+
def add (that: Int) = this ++ that
40+
static def unit = ""
41+
}
42+
43+
def sum[T: Monoid](xs: List[T]): T =
44+
(instance[T, Monoid].unit /: xs)(_ `add` _)
45+
46+
// --->
47+
{
48+
trait TypeClass {
49+
type This
50+
type Static[This]
51+
}
52+
53+
trait Implementation[From, To <: TypeClass] {
54+
type This = From
55+
def statics: To # Static[From]
56+
def inject(x: From): To { type This = From }
57+
}
58+
59+
trait SemiGroup extends TypeClass {
60+
def + (that: This): This
61+
}
62+
63+
trait Monoid extends SemiGroup {
64+
class Static[This] { def unit: This }
65+
}
66+
67+
implicit object extend_Int_Monoid extends Monoid#Static[Int] with Implementation[Int, Monoid] {
68+
def unit: Int = 0
69+
def inject($this: Int) = new Monoid {
70+
type This = Int
71+
def + (that: This): This = $this + that
72+
}
73+
}
74+
75+
implicit object extend_String_Monoid extends Monoid#Static[String] with Implementation[String, Monoid] {
76+
def unit = ""
77+
def inject($this: String): Monoid { type This = String } =
78+
new Monoid {
79+
type This = String
80+
def + (that: This): This = $this + that
81+
}
82+
}
83+
84+
def impl[From, To](implicit ev: Implementation[From, To]): Implementation[From, To] =
85+
ev
86+
87+
def sum[T](xs: List[T])(implicit $ev: Implementation[T, Monoid]) = {
88+
//val ev = impl[T, Monoid]
89+
($ev.statics.unit /: xs)((x, y) => $ev.inject(x) + y)
90+
}
91+
}
92+
93+
// Ord
94+
95+
trait Ord {
96+
def compareTo(that: This): Int
97+
def < (that: This) = compareTo < 0
98+
def > (that: This) = compareTo > 0
99+
}
100+
101+
extend List[type T : Ord] : Ord {
102+
def compareTo(that: List[T]): Int = (this, that) match {
103+
case (Nil, Nil) => 0
104+
case (Nil, _) => -1
105+
case (_, Nil) => +1
106+
case (x :: xs, y :: ys) =>
107+
val fst = x.compareTo(y)
108+
if (fst != 0) fst else xs.compareTo(ys)
109+
}
110+
}
111+
112+
// Functor and Monad
113+
114+
trait Functor[A] {
115+
object type ThisC[A] <: Functor[A]
116+
object def pure[A]: ThisC[A]
117+
118+
def map[B](f: A => B): ThisC[B]
119+
}
120+
121+
// Generically, `pure[A]{.map(f)}^n`
122+
def develop[A, F[X] : Functor[X]](n: Int, f: A => A): F[A] =
123+
if (n == 0) Functor.objects[F].pure[A]
124+
else develop[A, F](n - 1, f).map(f)
125+
126+
trait Monad[A] extends Functor[A] {
127+
object type ThisC[A] <: Monad[A]
128+
129+
def flatMap[B](f: A => ThisC[B]): ThisC[B]
130+
def map[B](f: A => B) = this.flatMap(f.andThen(pure))
131+
}
132+
133+
extend List[type T] : Monad[T] {
134+
object type ThisC[A] = List[A]
135+
object def pure[A] = Nil
136+
137+
def flatMap[B](f: A => List[B]): List[B] = this match {
138+
case x :: xs => f(x) ++ xs.flatMap(f)
139+
case Nil => Nil
140+
}
141+
}
142+
143+
extend (type T[X]: Monad[X])[T[type A]] {
144+
def flatten: T[A] = this.flatMap(identity)
145+
}
146+
147+
// Iterables
148+
149+
trait MonoIterable[A] {
150+
object type ThisC[A] <: MonoIterable[A]
151+
object def empty: This[A]
152+
object def apply(xs: A*): This[A]
153+
154+
def filter(p: A => Boolean): This[A]
155+
}
156+
157+
trait Iterable[A] extends MonoIterable[A] {
158+
object type ThisC[A] <: Iterable[A]
159+
160+
def map[B](f: A => B): ThisC[B]
161+
def flatMap[B](f: A => ThisC[B]): ThisC[B]
162+
}
163+
164+
extend String : MonoIterable[Char] {
165+
object type ThisC[A] = String
166+
object def empty = ""
167+
object def apply(xs: A*) = xs.mkString
168+
169+
def filter(p: Char => Boolean): String = ...
170+
def map(f: Char => Char): String = ...
171+
}
172+
173+
extend String : Iterable[Char] {
174+
object type ThisC[A] = IndexedSeq[A]
175+
176+
def map[B](f: Char => B): IndexedSeq[B] = ...
177+
def flatMap[B](f: Char => IndexedSeq[B]): IndexedSeq[B] = ...
178+
}
179+
180+
extend List[type T] : Iterable[T] {
181+
object type ThisC[A] = List[A]
182+
object def empty = Nil
183+
object def apply(xs: A*) = (xs /: Nil)(_ :: _)
184+
185+
def filter(p: T => Boolean): List[T] = ...
186+
def map[B](f: T => B): List[B] = ...
187+
def flatMap[B](f: T => List[B]): List[B] = ...
188+
}
189+
190+
class Foo {
191+
192+
}
193+
object Foo {
194+
195+
}
196+
}

0 commit comments

Comments
 (0)