abstract class Iter[I,A]{
def getValue(i : I) : Option[A]
def getNext(i : I) : I
}
defined [32mclass[39m [36mIter[39m
implicit def ListIter[A] : Iter[List[A], A] = new Iter[List[A], A]{
def getValue(i : List[A]) : Option[A] = i.headOption
def getNext( i : List[A]) : List[A] = i.tail
}
defined [32mfunction[39m [36mListIter[39m
def sumElements[I](xs : I)(implicit proxy : Iter[I, Int]) : Int = proxy.getValue(xs) match{
case None => 0
case Some(n) => n + sumElement(proxy.getNext(xs))
}
def printElements[I, X](xs : I)(implicit proxy : Iter[I, X]) : Unit = proxy.getValue(xs) match{
case None =>
case Some(n) => {println(n) ; printElements(proxy.getNext(xs)) ; }
}
defined [32mfunction[39m [36msumElements[39m
defined [32mfunction[39m [36mprintElements[39m
val I = List(3, 4, 5, 1)
sumElements(I)
printElements(I)
3
4
5
1
[36mI[39m: [32mList[39m[[32mInt[39m] = [33mList[39m([32m3[39m, [32m4[39m, [32m5[39m, [32m1[39m)
[36mres5_1[39m: [32mInt[39m = [32m13[39m
import scala.language.higherKinds
import scala.language.implicitConversions
abstract class Dyn2[S[_,_], A]{
type Data
val d: Data
val i : S[Data, A]
}
object Dyn2 {
// 실제 동작 함수. ii 에 incIter 동작 인스턴스가 들어가고
implicit def apply[S[_,_],D,A](dd : D)(implicit ii : S[D,A]) : Dyn2[S,A] = new Dyn2[S,A]{
type Data = D
val d : Data = dd
val i : S[Data, A] = ii
}
implicit def methods[S[_,_], A](d : Dyn2[S,A]) : S[d.Data, A] = d.i
}
/*********************************************************************
<< Dyn2 인스턴스 는 <타입클래스 정보 S > <반환할 데이터 타입 A> 로 초기화하고
<타입 클래스가 다룰 데이터 구조 D>를 입력받는다. >>>
val x : Dyn2[S,A](D) >>> x.d = 데이터구조 (주인공)
x.i = 타입클래스 인스턴스 정보( 실행기 )
<Dyn2 인스턴스 x> 를 만들면 무엇을 할 수 있는가?
x : Dyn2[Iter, Int] = Dyn2(List(1,2,3))
y : Dyn2[Iter, Int] = Dyn2(MyNode(1, Empty(), Empty()))
각각의 x, y 에 안에 들어있는 데이터구조와 타입클래스 인스턴스 정보로, Iter 타입클래스로 구현된 메서드를 모두 사용 가능하다.
Iter type class 의 interface method 들
sumElements(x.d)(x.i)
printElements(y.d)(y.i)
***********************************************************************/
[32mimport [39m[36mscala.language.higherKinds
[39m
[32mimport [39m[36mscala.language.implicitConversions
[39m
defined [32mclass[39m [36mDyn2[39m
defined [32mobject[39m [36mDyn2[39m
// type class 인스턴스 .... Int 데이터구조 들어왔을때 동작을 기술함 ... 하지만 직접 넣어줄 것이기 때문에 implicit 적지 않았다.
def incIter(max : Int) : Iter[Int, Int] = new Iter[Int, Int] {
def getValue(i : Int) = if (i <= max) Some(i) else None
def getNext(i : Int) = i + 1
}
// Dyn2 인스턴스를 생성해내는 방법
// getMyIter
def getMyIter(isInc: Boolean) : Dyn2[Iter, Int] = { //Dyn2[Iter, Int] 로 초기화한다.
if (isInc) Dyn2(0)(incIter(10)) //Dyn2.apply(0)(incIter(10)) // Dyn2(0) Int라는 데이터구조 를 다룬다.
else List(3, 1, 5) // Dyn2.apply(List(3,1,5))(listIter[Int]) // Dyn2(List[Int]) List[Int] 라는 데이터구조를 다룬다.
}
defined [32mfunction[39m [36mincIter[39m
defined [32mfunction[39m [36mgetMyIter[39m
val i1 : Dyn2[Iter, Int] = getMyIter(true)
printElements(i1.d)(i1.i) //printElements(0)(incIter(10))
val i2 : Dyn2[Iter, Int] = getMyIter(false)
printElements(i2.d)(i2.i) //printElements()
0
1
2
3
4
5
6
7
8
9
10
3
1
5
[36mi1[39m: [32mDyn2[39m[[32mIter[39m, [32mInt[39m] = $sess.cmd6Wrapper$Helper$Dyn2$$anon$1@74086131
[36mi2[39m: [32mDyn2[39m[[32mIter[39m, [32mInt[39m] = $sess.cmd6Wrapper$Helper$Dyn2$$anon$1@67d4c1f6
abstract class Dyn[T[_]]{
type Data
val d : Data
val proxy : T[Data]
}
object Dyn{
implicit def apply[D, T[_]](dd : D)(implicit tt : T[D]) : Dyn[T] = new Dyn[T] {
type Data = D
val d : Data = dd
val proxy : T[D] = tt
}
}
defined [32mclass[39m [36mDyn[39m
defined [32mobject[39m [36mDyn[39m
// 데이터 구조 정보
sealed abstract class MyTree[A]
case class Empty[A]() extends MyTree[A]
case class Node[A](value : A, left : MyTree[A], right : MyTree[A]) extends MyTree[A]
defined [32mclass[39m [36mMyTree[39m
defined [32mclass[39m [36mEmpty[39m
defined [32mclass[39m [36mNode[39m
// 데이터 구조 R 를 다루는 type class 본체
// iter 메서드는 Dyn2
abstract class Iterable[R,A]{
def iter(a: R) : Dyn2[Iter , A] // 데이터구조 R 을 넣으면 R 을 다루는 Dyn2[Iter, A](R) 를 돌려줄 것이다.
}
defined [32mclass[39m [36mIterable[39m
implicit def treeIterable : Iterable[MyTree[Int], Int] = new Iterable[MyTree[Int], Int]{
def iter(a : MyTree[Int]) : Dyn2[Iter, Int] = {
def go(I : MyTree[Int]) : List[Int] = I match{
case Empty() => Nil
case Node(v, left, right) => v :: (go(left) ++ go(right))
}
go(a) // List[Int] --> Dyn2[Iter, Int](List[Int]) --> Dyn2[Iter,Int](List[Int])(listIter(List[Int], Int))
}
}
defined [32mfunction[39m [36mtreeIterable[39m
def sumElements2[R](xs : R)(implicit proxy : Iterable[R, Int]) = {
val cs = proxy.iter(xs) // Dyn2[Iter, Int](Iter 로 다룰수 있게 변형된 xs)
sumElements(cs.d)(cs.i)
}
defined [32mfunction[39m [36msumElements2[39m
val t : MyTree[Int] = Node(1, Empty(), Empty())
sumElements2(t)
[36mt[39m: [32mMyTree[39m[[32mInt[39m] = Node(1,Empty(),Empty())
[36mres22_1[39m: [32mInt[39m = [32m1[39m