testList[List[Int]]
implicit def listIter[A] : Iter[List[A], A] =
new Iter[List[A],A] {
def getValue(a: List[A]) = a.headOption
def getNext(a: List[A]) = a.tail }
implicit def listIF[A] : ListIF[List[A],A] =
new ListIF[List[A],A] {
def empty: List[A] = Nil
def head(l: List[A]) = l.headOption
def tail(l: List[A]) = l.tail
def cons(a: A, l: List[A]) = a :: l
def append(l1: List[A], l2: List[A]) = l1 ::: l2
}
Tree 예제
trait ListIF[L,A] {
def empty : L
def head(l: L) : Option[A]
def tail(l: L) : L
def cons(a:A,l:L):L
def append(l1: L, l2: L) : L
}
trait TreeIF[T,A] {
def empty : T
def node(a:A,l:T,r:T):T
def head(t: T) : Option[A]
def left(t: T) : T
def right(t: T) : T
}
def testList[L](implicit LI: ListIF[L,Int], IT: Iter[L,Int]) {
val l = LI.cons(3, LI.cons(5, LI.cons(2, LI.cons(1, LI.empty))))
println(sumElements(l)) //sumElements(l)(listIter[Int])
printElements(l) //printElements(l)(listIter[Int])
}
def testTree[T](implicit TI: TreeIF[T,Int], ITR: Iterable[T,Int]) {
val t: T = TI.node(3, TI.node(4, TI.empty, TI.empty), TI.node(2, TI.empty, TI.empty))
println(sumElements2(t))
printElements2(t)
}
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]
implicit def treeIF[A] : TreeIF[MyTree[A],A] = new TreeIF[MyTree[A],A] {
def empty = Empty()
def node(a: A, l: MyTree[A], r: MyTree[A]) = Node(a,l,r)
def head(t: MyTree[A]) = t match {
case Empty() => None
case Node(v,_,_) => Some(v)
}
def left(t: MyTree[A]) = t match {
case Empty() => t
case Node(_,lt,_) => lt
}
def right(t: MyTree[A]) = t match {
case Empty() => t
case Node(_,_,rt) => rt }
}
슬라이드 233쪽
def treeIterable[L,A](implicit IF: ListIF[L,A], IT: Iter[L,A]) : Iterable[MyTree[A], A] = new Iterable[MyTree[A], A] {
type Itr=L
def iter(a: MyTree[A]): L = a match {
case Empty() => IF.empty
case Node(v, left, right) => IF.cons (v, IF.append(iter(left), iter(right)))
}
val iterIF = IT
}
implicit def treeIterableList[A] = treeIterable[List[A],A]
이와 같이 코드를 interface level에서 작성해두면 list --> lazylist로 변환하기가 수월해 지는 등의 장점이 생김.
지난주 화, 목 수업 내용 매우 중요함.
지금까지의 내용이 중요하고 이 뒤는 중요도가 조금 떨어짐.
** 뭐랑 뭐가 연관이 됐는지가 명확하고 dependency가 뚜렷한 것. --> 교수님이 추구하셨던 코딩
내 코드가 수정이 됐을 때 어떤 영향을 미치는지도 명확하고 ..
슬라이드 235쪽
Refined Interfaces
trait ListProdIF[L,A] {
def empty : L
def cons(a:A,l:L):L
def append(l1: L, l2: L) : L
}
def treeIterable[L,A](implicit IF: ListProdIF[L,A], IT: Iter[L,A]) =
new Iterable[MyTree[A], A] {
type Itr=L
def iter(a: MyTree[A]): L = a match {
case Empty() => IF.empty
case Node(v, left, right) => IF.cons (v, IF.append(iter(left), iter(right)))
}
val iterIF = IT
}
implicit def treeIterableList[A] = treeIterable[List[A],A]
Linking Modules
implicit def List2ListProdIF[L,A](implicit IF: ListIF[L,A]) : ListProdIF[L,A] =
new ListProdIF[L,A] {
def empty = IF.empty
def cons(a: A, l: L) = IF.cons(a,l)
def append(l1: L, l2: L) = IF.append(l1, l2)
}
testList[List[Int]]
testTree[MyTree[Int]]
interface를 다양하게 입맛대로 만들 수 있음.
Iter being Iterable
implicit def iterIterable[I,A](implicit IT: Iter[I,A]) : Iterable[I,A] =
new Iterable[I, A] {
type Itr = I
val iterIF = IT
def iter(a: I) = a
}
val l = List(3,5,2,1)
sumElements2(l) //sumElements2(iterIterable(listIter[Int]))
printElements2(l) //printElements2(iterIterable(listIter[Int]))
I에 대한 Iter --> I에 대한 Iterable도 무조건 만들 수 있음.
Type class는 어떤 타입인지에 대해 상관없음. OOP 스타일이 들어와도 ㄱㅊ음.
OOP에서는 상속(extends ~~~ )을 받았어야 됐지만 타입클래스에서는 상속을 받지 않아도 됨.
Higer-kind Type Classes
'학교 공부 > 프로그래밍원리' 카테고리의 다른 글
HW3 - (1) (0) | 2022.11.25 |
---|---|
1122 Stacking with Type Classes (0) | 2022.11.22 |
11/10 Type Classes with Multiple Parameters (0) | 2022.11.10 |
PART 2 - Object-Oriented Programming (1) (0) | 2022.10.23 |
PART 1 - Exception & Handling , DataType (0929) (0) | 2022.10.20 |