1+ /** A possible type class encoding for
2+
3+ trait SemiGroup {
4+ def add(that: This): This
5+ }
6+
7+ trait Monoid extends SemiGroup
8+ common {
9+ def unit: This
10+ }
11+
12+ extension IntOps for Int : Monoid {
13+ def add(that: Int) = this + that
14+ }
15+ common {
16+ def unit = 0
17+ }
18+
19+ extension StringOps for String : Monoid {
20+ def add(that: Int) = this ++ that
21+ }
22+ common {
23+ def unit = ""
24+ }
25+
26+ def sum[T: Monoid](xs: List[T]): T =
27+ (instance[T, Monoid].unit /: xs)(_ `add` _)
28+
29+ */
30+ object runtime {
31+
32+ trait TypeClass {
33+ val common : TypeClassCommon
34+ type This = common.This
35+ }
36+
37+ trait TypeClassCommon { self =>
38+ type This
39+ type Instance <: TypeClass
40+ def inject (x : This ): Instance { val common : self.type }
41+ }
42+
43+ trait Extension [From , To <: TypeClass ] extends TypeClassCommon {
44+ type This = From
45+ type Instance = To
46+ }
47+
48+ implicit def inject [From ](x : From )
49+ (implicit ev : Extension [From , _]): ev.Instance { type This = From } =
50+ ev.inject(x)
51+ }
52+ import runtime ._
53+
54+ object semiGroups {
55+
56+ trait SemiGroup extends TypeClass {
57+ import common ._
58+ def add (that : This ): This
59+ }
60+ trait SemiGroupCommon extends TypeClassCommon {
61+ type Instance <: SemiGroup
62+ }
63+
64+ trait Monoid extends SemiGroup {
65+ val common : MonoidCommon
66+ import common ._
67+ }
68+ trait MonoidCommon extends SemiGroupCommon {
69+ type Instance <: Monoid
70+ def unit : This
71+ }
72+
73+ implicit object IntOps extends Extension [Int , Monoid ] with MonoidCommon { self =>
74+ type This = Int
75+ type Instance = Monoid
76+ def unit : Int = 0
77+ def inject ($this : Int ) = new Monoid {
78+ val common : self.type = self
79+ def add (that : This ): This = $this + that
80+ }
81+ }
82+
83+ implicit object StringOps extends Extension [String , Monoid ] with MonoidCommon { self =>
84+ type This = String
85+ type Instance = Monoid
86+ def unit = " "
87+ def inject ($this : String ) = new Monoid {
88+ val common : self.type = self
89+ def add (that : This ): This = $this .concat(that)
90+ }
91+ }
92+
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)
95+ }
96+
97+ /** Encoding for
98+
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+ }
107+
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+ }
115+
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)
124+ }
125+ }
126+ common {
127+ val minimum = Nil
128+ }
129+
130+ def min[T: Ord](x: T, y: T) = if (x < y) x else y
131+
132+ def inf[T: Ord](xs: List[T]): T = (instance[T, Ord].minimum /: xs)(_ `min` _)
133+ */
134+
135+ object ord {
136+
137+ trait Ord extends TypeClass {
138+ import common ._
139+ def compareTo (that : This ): Int
140+ def < (that : This ) = compareTo(that) < 0
141+ def > (that : This ) = compareTo(that) > 0
142+ }
143+ trait OrdCommon extends TypeClassCommon {
144+ type Instance <: Ord
145+ def minimum : This
146+ }
147+
148+ implicit object IntOrd extends Extension [Int , Ord ] with OrdCommon { self =>
149+ type This = Int
150+ type Instance = Ord
151+ val minimum : Int = Int .MinValue
152+ def inject ($this : Int ) = new Ord {
153+ val common : self.type = self
154+ def compareTo (that : This ): Int =
155+ if (this < that) - 1 else if (this > that) + 1 else 0
156+ }
157+ }
158+
159+ class ListOrd [T ](implicit ev : Extension [T , Ord ] with OrdCommon )
160+ extends Extension [List [T ], Ord ] with OrdCommon { self =>
161+ type This = List [T ]
162+ type Instance = Ord
163+ def minimum : List [T ] = Nil
164+ def inject ($this : List [T ]) = new Ord {
165+ val common : self.type = self
166+ def compareTo (that : List [T ]): Int = ($this , that) match {
167+ case (Nil , Nil ) => 0
168+ case (Nil , _) => - 1
169+ case (_, Nil ) => + 1
170+ case (x :: xs, y :: ys) =>
171+ val fst = x.compareTo(y)
172+ if (fst != 0 ) fst else xs.compareTo(ys)
173+ }
174+ }
175+ }
176+
177+ implicit def listOrd [T ](implicit ev : Extension [T , Ord ] with OrdCommon ): ListOrd [T ] =
178+ new ListOrd [T ]
179+
180+ def min [T ](x : T , y : T )(implicit ev : Extension [T , Ord ] with OrdCommon ): T =
181+ if (x < y) x else y
182+
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(_, _))
186+ }
187+ }
0 commit comments