Part 3 - 53쪽 / 전체 슬라이드 기준 264
205쪽에서 다뤘었음
Stacking with traits
Base
trait Stack[A] {
def get() : (A,Stack[A])
def put(x:A) : Stack[A]
}
Core
class BasicIntStack protected (xs: List[Int]) extends Stack[Int] {
override val toString = "Stack:" + xs.toString
def this() = this(Nil)
protected def mkStack(xs: List[Int]): Stack[Int] = new BasicIntStack(xs)
def get(): (Int,Stack[Int]) = (xs.head, mkStack(xs.tail))
def put(x: Int): Stack[Int] = mkStack(x :: xs)
}
val s0 = new BasicIntStack
val s1 = s0.put(3)
val s2 = s1.put(-2)
val s3 = s2.put(4)
val (v1,s4) = s3.get()
val (v2,s5) = s4.get()
custom
trait Doubling extends Stack[Int] {
abstract override def put(x: Int): Stack[Int] = super.put(2 * x)
}
trait Incrementing extends Stack[Int] {
abstract override def put(x: Int): Stack[Int] = super.put(x + 1)
}
trait Filtering extends Stack[Int] {
abstract override def put(x: Int): Stack[Int] =
if (x >= 0) super.put(x)
else this
}
...
multiple inheritance 로 했었음
extends ~ with ~ with ~ with
오늘 수업 시간에 다룰 내용은
Stacking with Type classes
Base 구현
trait Stack[S,A]{
def empty : S
def get(s:S):(A,S)
def put(s:S)(x:A):S
}
//Int stack으로 하나 구현
def testStack[S](implicit stk:Stack[S,Int])={
val s0 = stk.empty
val s1 = stk.put(s0)(3) //s0에 3을 넣어라
val s2 = stk.put(s1)(-2)
val s3 = stk.put(s2)(4)
val (v1,s4) = stk.get(s3) //tuple을 이용해 여러개의 변수에 동시에 값 넣기
val (v2,s5) = stk.get(s4)
(v1,v2)
}
core 구현 (Int Stack으로 구현)
implicit def StackListInt:Stack[List[Int],Int]= new Stack[List[Int],Int] {
val empty = List()
def get(s:List[Int]) = (s.head, s.tail)
def put(s:List[Int])(x:Int) = x :: s
}
Modifying Traits
토핑 올리기
스택을 받아서 스택을 리턴하는 함수를 구현하자.
def IntStackWithPut[S](parent:Stack[S,Int], newPut:(S,Int)=>S):Stack[S,Int]= new Stack[S,Int]{
def empty = parent.empty
def get(s:S) = parent.get(s)
def put(s:S)(x:Int) = newPut(s,x)
}
def Doubling[S] (parents:Stack[S,Int]):Stack[S,Int] =
IntStackWithPut(parent,(s,x)=>parent.put(s)(2*x))
def Incrementing[S] (parents:Stack[S,Int]):Stack[S,Int] =
IntStackWithPut(parent,(s,x)=>parent.put(s)(x+1))
def Filterint[S](parent:Stack[S,Int]):Stack[S,Int]=
IntStackWithPut(parent,(s,x)=>if(x>=0) parent.put(s)(x) else s)
코드 재사용이 잘 되고 있는 것을 확인할 수 있다.
코드 실행 결과)
testStack(Filtering(Incrementing(Doubling(StackListInt)))
res 0 : (10,8)
testStack(Doubling(Doubling(StackListInt)))
res 1:(16,-8)
==> 내가 쓰고 싶은 함수를 인자로 받아서 조금 수정해가면서 reuse 하는 것이 composition
상속은 코드 관리가 어려움. 상위 코드를 조금 수정하는 순간 뒤죽박죽이 되니까
OOP는 문제가 많고 그 대안은 Type Class임.
추상화하는 것(interface)과, 기존 코드의 재활용성(Composition) 관점에서 자연스럽게 지원하고 있는 것은 타입클래스임.
++ Implementaion : Sorted Stack
def sortedStqackList : Stack[List[Int],Int] = new Stack[List[Int],Int] {
def empty = List()
def get(s:List[Int]):(Int,List[Int]) = (s.head, s.tail)
def put(s:List[Int](x:Int):List[Int]={
def go(l:List[Int]):List[Int] = l match {
case Nil => x::Nil
case hd::tl => if(x<=hd) x::l else hd::go(tl)
}
go(s)
}
}
'학교 공부 > 프로그래밍원리' 카테고리의 다른 글
HW 3- (2) reshape 구현하기 (0) | 2022.11.26 |
---|---|
HW3 - (1) (0) | 2022.11.25 |
11/16 Type Classes With Multiple Parameters & Higher-kind (0) | 2022.11.15 |
11/10 Type Classes with Multiple Parameters (0) | 2022.11.10 |
PART 2 - Object-Oriented Programming (1) (0) | 2022.10.23 |