SlideShare uma empresa Scribd logo
1 de 21
Baixar para ler offline
Haskell
Study
6. type & type class 2
Algebraic Data type
Haskell에서 새로운 데이터 타입을 정의할 때는 data 키워드를 이용합니다. 표준에서 Bool 데이터
타입은 아래와 같이 선언되어 있습니다.
data Bool = False | True
data 다음 부분이 타입의 이름이고, = 이후의 부분이 해당 타입의 생성자(값 생성자 - value
constructor)를 가리킵니다. | (or)을 이용해 여러 개의 생성자를 만들 수 있습니다. 위의 data
구문은 'Bool 타입은 False 또는 True라는 값 생성자를 가진다' 라는 의미로 볼 수 있습니다. 타입
이름, 값 생성자는 반드시 대문자로 시작해야합니다.
Algebraic Data type
Haskell에서 어떤 도형에 대한 정보를 나타내고 싶다고 해 봅시다. 예를 들어 원은 중점의 좌표 및
반지름, 사각형은 좌상단과 우하단의 좌표 등으로 표현할 수 있습니다. 이런걸 튜플을 이용해 표현할
수도 있지만, 튜플은 의미를 명확히 파악하기가 쉽지 않기 때문에 새로운 타입을 정의하는 게 좋겠죠.
data Shape = Circle Float Float Float
			 | Rectangle Float Float Float Float
위의 예제와 같이 각 값 생성자들은 필드(Field)를 가질 수 있습니다. Circle 값 생성자는 Float형의
값 3가지를 필드로 갖게 되고(첫 두개는 중점, 나머지 하나는 반지름), Rectangle 값 생성자는 Float
형의 값 4가지를 필드로 갖게 되는 거죠(첫 두개는 좌상단, 나머지 두개는 우하단 좌표).
Algebraic Data type
값 생성자는 사실 필드의 값이 주어졌을 때 해당 타입의 값을 반환하는 함수라고 볼 수 있습니다.
Prelude> :t Circle
Circle :: Float -> Float -> Float -> Shape
Prelude :t Rectangle
Rectangle :: Float -> Float -> Float -> Float -> Shape
그리고 값 생성자는 아래와 같이 해당 타입의 값에 대한 함수의 패턴 매칭에서 사용할 수 있습니다.
surface :: Shape -> Float
surface (Circle _ _ r) = pi * r ^ 2
surface (Rectangle x1 y1 x2 y2) = abs $ (x2 - x1) * (y2 - y1)
Algebraic Data type
Bool 타입의 값 생성자 True, False처럼 값 생성자는 필드 값을 가지고 있을 수도 있고 아닐 수도
있습니다. 그리고, 앞에서 봤듯이 값 생성자 역시 함수이기 때문에 커링이 되고, 따라서 부분 적용의
이점을 값 생성자에도 그대로 적용시킬 수 있습니다.
{-- 맨 끝에 deriving Show를 붙이면 Show 타입 클래스를 자동으로 상속받게 됩니다. 조금 나중에
다루니 여기서는 일단 "내가 직접 만든 데이터 타입을 결과 창에 띄우려면 deriving Show를 써줘야
한다" 정도로만 이해해주시면 되겠습니다. --}
data Shape = Circle Float Float Float
			 | Rectangle Float Float Float Float deriving Show
Prelude> map (Circle 10 20) [4,5,6,6]
[Circle 10 20 4, Circle 10 20 5, Circle 10 20 6, Circle 10 20 6]
Record Syntax
어떤 사람에 대한 정보를 타입으로 나타내고 싶다고 합시다.
data Person = Person String String Int String deriving (Show)
첫 두 개는 각각 이름과 성, 세 번째는 나이, 네 번째는 주소라고 합시다. 이제 이 데이터 타입으로부터
각 필드의 값을 가져오려면 아래와 같은 함수들을 만들어야합니다.
firstname (Person firstname _ _ _) = firstname
lastname (Person _ lastname _ _) = lastname
age (Person _ _ age _) = age
address (Person _ _ _ address) = address
Record Syntax
척 봐도 알겠지만 앞에서처럼 각 필드의 값을 가져오기 위해 일일히 함수를 만들어줘야한다는 것은
굉장히 불편하고 귀찮은 일입니다. Haskell에서는 이런 상황을 위해 Record Syntax라는 문법을
제공합니다.
data Person = Person { firstname :: String
, lastname :: String
, age :: Int
, address :: String } deriving (Show)
Prelude> let nam = Person "nam" "hyeonuk" 21 "blahblah"
Prelude> age nam
21
Record Syntax
Record syntax는 앞에서와 같이 값 생성자 뒤에 중괄호 ({}), 그 내부에 각 필드의 이름과 타입
어노테이션(::)을 통한 해당 필드의 타입 명시로 이루어져있습니다. Record syntax로 생성된 타입은
각 필드의 값을 가져오는 함수가 자동으로 생성됩니다. Record syntax로 작성된 데이터 타입은 해당
타입의 값 생성자로 값을 만들 때에도 Record syntax 스타일을 사용할 수 있습니다. 이 방식으로 쓸
때에는 반드시 필드의 순서가 선언 순서와 일치할 필요는 없습니다.
data Circle = Circle { origin :: (Int, Int)
, radius :: Int } deriving (Show)
Prelude> let c = Circle { radius = 5, origin = (0,0) }
Prelude> origin c
(0,0)
Type parameter
C++의 템플릿과 비슷한 개념으로 Haskell에는 타입 생성자(Type constructor)라는 것이 있습니다.
타입 생성자는 타입을 매개 변수로 받아서 새로운 타입을 만들어냅니다. 표준에 있는 유용한 타입
생성자인 Maybe를 예로 들어봅시다.
data Maybe a = Nothing | Just a
여기서 a가 바로 타입 매겨변수입니다. Maybe 타입 생성자는 Nothing 값 생성자가 아니라면 임의의
타입 a에 대해 해당 타입의 값을 하나 필드로 들고 있는 값을 만들어내죠. Maybe Int, Maybe
Char같은 것들이 하나의 타입이 되는 겁니다. Maybe Int 타입의 값으로 Just 3, Just 22
같은 게 있을 수 있고, Maybe Char 타입의 값으로 Just 'a', Just 'c'같은 값들이 있을 수
있겠죠.
Type parameter
여태껏 써왔던 리스트(list)역시 일종의 타입 매개변수를 받습니다. 여태껏 우리는 임의의 타입에 대한
리스트를 써왔죠. 실제로는 이 리스트 역시 임의의 타입 a에 대해 [a] 타입을 생성하는 타입 생성자를
기반으로 동작하고 있는 것입니다.
타입 매개변수는 내부에 들고 있는 필드의 값이 모든 종류의 값에 대해 일반적으로 동작할 필요가
있을 경우에 사용하면 굉장히 좋습니다.
Type synonyms
어떤 타입에 대해 별명을 붙여주고 싶을 때 type 키워드를 사용할 수 있습니다. C언어의 typedef,
C++ 11의 using 키워드와 동일한 역할이라고 생각하시면 됩니다. type 키워드는 내부적으로는
완전히 동일하나 이름만 서로 다른 데이터 타입을 만들어냅니다(서로 호환도 됩니다). type 키워드는
코드의 가독성을 위해 사용합니다. 대표적인 예로 String과 [Char]을 들 수 있겠네요.
type Point = (Int, Int)
distance :: Point -> Point -> Int
distance (x1,y1) (x2,y2) = sqrt $ (x2-x1)^2 + (y2-y1)^2
Derived instances
Haskell의 기본 타입클래스들은 deriving 키워드를 이용해 별도의 정의 없이 해당 타입 클래스의
기본 구현체를 상속받을 수 있습니다. 어떤 타입이 해당 타입 클래스에 정의된 동작을 지원할 때 해당
타입 클래스의 인스턴스(instance)라고 합니다. deriving 키워드를 이용하면 해당 타입 클래스의
동작을 기본적으로 구현하게 됩니다. 앞에서도 봤듯이 deriving Show 를 이용하면 컴파일러가
자동으로 해당 타입이 Show 타입 클래스의 행동을 구현하게 만들어 주죠. Show외에도 Eq, Ord,
Enum, Bounded, Show, Read 등에 대해 deriving 키워드를 이용할 수 있습니다.
data Person = Person { firstname :: String
, lastname :: String
, age :: Int } deriving (Show, Eq)
Prelude> Person "nam" "hyeonuk" 21 == Person "nam" "hyeonuk" 21
True
Recursive Data
데이터 타입은 재귀적인 구조를 가질 수 있습니다. list를 직접 구현해봅시다.
data List a = Empty
| Cons a (List a) deriving (Show, Read, Eq, Ord)
Prelude> 5 `Cons` Empty
Cons 5 Empty
Prelude> 4 `Cons` 5 `Cons` Empty
Cons 4 (Cons 5 Empty)
위의 List 데이터 타입은 Empty(빈 리스트 [])와 Cons(:)라는 두 개의 값 생성자를 가집니다.
그리고 Cons 생성자는 다시 자신의 필드로 List a를 가집니다. 재귀적인 구조가 되는 거죠. 이 재귀적
구조를 이용해서 위와 같이 리스트를 구현할 수 있습니다.
Recursive Data
동일한 방식으로 바이너리 트리 역시 구현할 수 있습니다.
data Tree a = EmptyTree
| Node a (Tree a) (Tree a) deriving (Show, Read, Eq)
위 트리구조에 삽입 / 삭제 함수를 적절히 원하는 구조로 작성하면 자신의 필요에 맞게 간단한 Binary
Search Tree 등을 구현할 수 있습니다.
typeclass
이번엔 직접 타입 클래스를 한 번 만들어봅시다. 우선 예제로 표준에 있는 Eq 타입 클래스가 어떻게
구현되어있는지 먼저 살펴보죠.
class Eq a where
	(==) :: a -> a -> Bool
	(/=) :: a -> a -> Bool
	 x == y = not (x /= y)
	 x /= y = not (x == y)
새로운 타입 클래스를 정의하기 위해 class 키워드를 사용합니다. class 뒤에 타입 클래스의 이름과
해당 타입 클래스에 속하는 타입을 지칭하기 위한 타입 매개변수, 그리고 where 이후에 해당 타입
클래스에 속하는 타입들이 수행할 수 있어야만 하는 동작들을 정의합니다.
typeclass
class Eq a where
	(==) :: a -> a -> Bool
	(/=) :: a -> a -> Bool
	 x == y = not (x /= y)
	 x /= y = not (x == y)
타입 클래스 정의의 맨 아래쪽을 보면 x == y와 x /= y가 서로 재귀적으로 정의되어 있는 것을 볼
수 있습니다. 이 재귀적 정의에 의해 == 또는 /= 둘 중 하나만 정의하면 나머지 하나도 그 정의에
의해 자동으로 정의가 됩니다. 이 덕분에 Eq 타입 클래스에 속하는 타입이 ==과 /= 동작을 어떻게
수행해야할 지 정의할 때 둘 모두를 정의할 필요 없이, 정의하기 편한 것 하나만 정의하면 되는
편의성을 얻을 수 있죠.
typeclass
이제 특정 타입이 어떤 타입 클래스의 인스턴스가 되려면 어떻게 해야하는지 정의하는 방법을
살펴봅시다.
data TrafficLight = Red | Yellow | Green
신호등 색깔을 나타낸 데이터 타입입니다. 이 타입이 Eq 타입 클래스에 속하게 만들려면 아래와 같이
해야합니다.
instance Eq TrafficLight where
	Red == Red = True
	Green == Green = True
	Yellow == Yellow = True
	 _ == _ = False
typeclass
instance Eq TrafficLight where
	Red == Red = True
	Green == Green = True
	Yellow == Yellow = True
	 _ == _ = False
타입 클래스의 인스턴스를 만들 때는 위와 같이 instance 키워드를 이용합니다. 그리고 원래
타입 매개변수 a로 표현했던 부분에 실제로 인스턴스로 만들고자 하는 타입을 적어주고, where
뒤에 정의해야하는 함수들의 동작을 정의해줍니다. 이 경우 TrafficLight에 대한 == 함수만을
정의해주었고, /= 함수는 재귀적 정의 ( not ( x == y ) )에 의해 자동으로 정의가 됩니다.
typeclass
어떤 타입 클래스의 sub typeclass도 만들 수 있습니다. 예를 들어, Ord 타입 클래스는 아래와 같이
정의되어 있습니다.
class (Eq a) => Ord a where
	compare :: a -> a -> Ording
	... -- 자세한 구현은 생략
위와 같이 이전에 타입 클래스 제약조건을 표기할 때 썼던 =>을 이용해 sub typeclass를 만들 수
있습니다. 위 선언의 의미는 Ord 타입 클래스에 속하기 위해서는 반드시 Eq 타입 클래스에 먼저
속해야만 한다는 것입니다. 이런 제약은 타입 클래스의 동작을 정의하기 위해 다른 타입 클래스의
동작이 필요한 경우 사용할 수 있습니다.
typeclass
class (Eq m) => Eq (Maybe m) where
	 Just x == Just y = x == y
	Nothing == Nothing = True
	 _ == _ = False
Maybe 타입의 Eq 타입 클래스 인스턴스 정의입니다. 두 Just 값 비교는 그 내부 값이 같은 지
아닌지로 판별하고 있는데, 이 때 == 함수를 쓰려면 Maybe의 타입 매개변수 역시 Eq 타입 클래스에
속해야만 합니다. 따라서 Eq m 이라는 제약조건을 걸어 Just x 와 Just y 의 비교에 x == y를 사용할
수 있게 만들어야합니다.
연습 문제
•	binary search tree
BST를 만들어 봅시다. 트리 구조를 저장하기 위한 새로운 타입과, 트리에 원소를 삽입하는 함수, 어떤
원소가 해당 트리에 존재하는지 검색하는 함수 등을 구현해봅시다. BST는 각 노드에 대해 자신의 왼쪽
자식은 모두 자신보다 값이 작아야하며, 자신의 오른쪽자식은 모두 자신보다 값이 큰 트리를 말합니다.
또한 각 노드의 값은 유일해야합니다(중복되는 값이 존재하지 않습니다).
추가적으로 좀 더 연습을 해보고 싶으신 분은 노드를 삭제하는 함수, 혹은 Red-Black Tree나 AVL
Tree같이 균형잡인 트리를 만드는 코드를 한 번 작성해보시는 것도 도움이 될 것 같습니다.

Mais conteúdo relacionado

Mais procurados

Haskell study 13
Haskell study 13Haskell study 13
Haskell study 13Nam Hyeonuk
 
Php by shivitomer
Php by shivitomerPhp by shivitomer
Php by shivitomerShivi Tomer
 
JavaScript - Chapter 10 - Strings and Arrays
 JavaScript - Chapter 10 - Strings and Arrays JavaScript - Chapter 10 - Strings and Arrays
JavaScript - Chapter 10 - Strings and ArraysWebStackAcademy
 
C programming Training in Ambala ! Batra Computer Centre
C programming Training in Ambala ! Batra Computer CentreC programming Training in Ambala ! Batra Computer Centre
C programming Training in Ambala ! Batra Computer Centrejatin batra
 
PHP - DataType,Variable,Constant,Operators,Array,Include and require
PHP - DataType,Variable,Constant,Operators,Array,Include and requirePHP - DataType,Variable,Constant,Operators,Array,Include and require
PHP - DataType,Variable,Constant,Operators,Array,Include and requireTheCreativedev Blog
 
Function template
Function templateFunction template
Function templateKousalya M
 
Structure in c language
Structure in c languageStructure in c language
Structure in c languagesangrampatil81
 
Strings Functions in C Programming
Strings Functions in C ProgrammingStrings Functions in C Programming
Strings Functions in C ProgrammingDevoAjit Gupta
 
Functional Core and Imperative Shell - Game of Life Example - Haskell and Scala
Functional Core and Imperative Shell - Game of Life Example - Haskell and ScalaFunctional Core and Imperative Shell - Game of Life Example - Haskell and Scala
Functional Core and Imperative Shell - Game of Life Example - Haskell and ScalaPhilip Schwarz
 
Javascript built in String Functions
Javascript built in String FunctionsJavascript built in String Functions
Javascript built in String FunctionsAvanitrambadiya
 
self_refrential_structures.pptx
self_refrential_structures.pptxself_refrential_structures.pptx
self_refrential_structures.pptxAshishNayyar12
 

Mais procurados (20)

Haskell study 13
Haskell study 13Haskell study 13
Haskell study 13
 
Php by shivitomer
Php by shivitomerPhp by shivitomer
Php by shivitomer
 
JavaScript - Chapter 10 - Strings and Arrays
 JavaScript - Chapter 10 - Strings and Arrays JavaScript - Chapter 10 - Strings and Arrays
JavaScript - Chapter 10 - Strings and Arrays
 
Oops presentation
Oops presentationOops presentation
Oops presentation
 
C programming Training in Ambala ! Batra Computer Centre
C programming Training in Ambala ! Batra Computer CentreC programming Training in Ambala ! Batra Computer Centre
C programming Training in Ambala ! Batra Computer Centre
 
Dictionary
DictionaryDictionary
Dictionary
 
PHP - DataType,Variable,Constant,Operators,Array,Include and require
PHP - DataType,Variable,Constant,Operators,Array,Include and requirePHP - DataType,Variable,Constant,Operators,Array,Include and require
PHP - DataType,Variable,Constant,Operators,Array,Include and require
 
Function template
Function templateFunction template
Function template
 
Structure and union
Structure and unionStructure and union
Structure and union
 
Best sql plsql material
Best sql plsql materialBest sql plsql material
Best sql plsql material
 
SQL(database)
SQL(database)SQL(database)
SQL(database)
 
Php array
Php arrayPhp array
Php array
 
plsql.ppt
plsql.pptplsql.ppt
plsql.ppt
 
Structure in c language
Structure in c languageStructure in c language
Structure in c language
 
Structure in c
Structure in cStructure in c
Structure in c
 
Strings Functions in C Programming
Strings Functions in C ProgrammingStrings Functions in C Programming
Strings Functions in C Programming
 
Perl Scripting
Perl ScriptingPerl Scripting
Perl Scripting
 
Functional Core and Imperative Shell - Game of Life Example - Haskell and Scala
Functional Core and Imperative Shell - Game of Life Example - Haskell and ScalaFunctional Core and Imperative Shell - Game of Life Example - Haskell and Scala
Functional Core and Imperative Shell - Game of Life Example - Haskell and Scala
 
Javascript built in String Functions
Javascript built in String FunctionsJavascript built in String Functions
Javascript built in String Functions
 
self_refrential_structures.pptx
self_refrential_structures.pptxself_refrential_structures.pptx
self_refrential_structures.pptx
 

Semelhante a Haskell study 6

Scala type class pattern
Scala type class patternScala type class pattern
Scala type class patternYong Joon Moon
 
Smalltalk at Altlang 2008
Smalltalk at Altlang 2008Smalltalk at Altlang 2008
Smalltalk at Altlang 2008daliot
 
델파이 코딩 스타일과 아키텍처
델파이 코딩 스타일과 아키텍처델파이 코딩 스타일과 아키텍처
델파이 코딩 스타일과 아키텍처Devgear
 
이펙티브 C++ 스터디
이펙티브 C++ 스터디이펙티브 C++ 스터디
이펙티브 C++ 스터디quxn6
 
파이썬정리 20160130
파이썬정리 20160130파이썬정리 20160130
파이썬정리 20160130Yong Joon Moon
 
Data Structure 4
Data Structure 4Data Structure 4
Data Structure 4yonsei
 
2014-15 Intermediate C++ Study #7
2014-15 Intermediate C++ Study #72014-15 Intermediate C++ Study #7
2014-15 Intermediate C++ Study #7Chris Ohk
 
Swift3 : class and struct(+property+method)
Swift3 : class and struct(+property+method)Swift3 : class and struct(+property+method)
Swift3 : class and struct(+property+method)승욱 정
 
Javascript 완벽 가이드 정리
Javascript 완벽 가이드 정리Javascript 완벽 가이드 정리
Javascript 완벽 가이드 정리ETRIBE_STG
 
자바프로그래머를 위한 스칼라
자바프로그래머를 위한 스칼라자바프로그래머를 위한 스칼라
자바프로그래머를 위한 스칼라Jong Gook Bae
 
2014-15 Intermediate C++ Study #6
2014-15 Intermediate C++ Study #62014-15 Intermediate C++ Study #6
2014-15 Intermediate C++ Study #6Chris Ohk
 
파이썬+주요+용어+정리 20160304
파이썬+주요+용어+정리 20160304파이썬+주요+용어+정리 20160304
파이썬+주요+용어+정리 20160304Yong Joon Moon
 
일단 시작하는 코틀린
일단 시작하는 코틀린일단 시작하는 코틀린
일단 시작하는 코틀린Park JoongSoo
 
Programming java day2
Programming java day2Programming java day2
Programming java day2Jaehoonyam
 
UML Diagram about Class / Activity / Object (Korean Language)
UML Diagram about Class / Activity / Object (Korean Language)UML Diagram about Class / Activity / Object (Korean Language)
UML Diagram about Class / Activity / Object (Korean Language)Prof. Chung
 
Start IoT with JavaScript - 4.객체1
Start IoT with JavaScript - 4.객체1Start IoT with JavaScript - 4.객체1
Start IoT with JavaScript - 4.객체1Park Jonggun
 
[아꿈사] The C++ Programming Language 11장 연산자 오버로딩
[아꿈사] The C++ Programming Language 11장 연산자 오버로딩[아꿈사] The C++ Programming Language 11장 연산자 오버로딩
[아꿈사] The C++ Programming Language 11장 연산자 오버로딩해강
 

Semelhante a Haskell study 6 (20)

STL study (skyLab)
STL study (skyLab)STL study (skyLab)
STL study (skyLab)
 
강의자료3
강의자료3강의자료3
강의자료3
 
Scala type class pattern
Scala type class patternScala type class pattern
Scala type class pattern
 
Smalltalk at Altlang 2008
Smalltalk at Altlang 2008Smalltalk at Altlang 2008
Smalltalk at Altlang 2008
 
델파이 코딩 스타일과 아키텍처
델파이 코딩 스타일과 아키텍처델파이 코딩 스타일과 아키텍처
델파이 코딩 스타일과 아키텍처
 
이펙티브 C++ 스터디
이펙티브 C++ 스터디이펙티브 C++ 스터디
이펙티브 C++ 스터디
 
파이썬정리 20160130
파이썬정리 20160130파이썬정리 20160130
파이썬정리 20160130
 
Data Structure 4
Data Structure 4Data Structure 4
Data Structure 4
 
2014-15 Intermediate C++ Study #7
2014-15 Intermediate C++ Study #72014-15 Intermediate C++ Study #7
2014-15 Intermediate C++ Study #7
 
Swift3 : class and struct(+property+method)
Swift3 : class and struct(+property+method)Swift3 : class and struct(+property+method)
Swift3 : class and struct(+property+method)
 
Javascript 완벽 가이드 정리
Javascript 완벽 가이드 정리Javascript 완벽 가이드 정리
Javascript 완벽 가이드 정리
 
자바프로그래머를 위한 스칼라
자바프로그래머를 위한 스칼라자바프로그래머를 위한 스칼라
자바프로그래머를 위한 스칼라
 
2014-15 Intermediate C++ Study #6
2014-15 Intermediate C++ Study #62014-15 Intermediate C++ Study #6
2014-15 Intermediate C++ Study #6
 
파이썬+주요+용어+정리 20160304
파이썬+주요+용어+정리 20160304파이썬+주요+용어+정리 20160304
파이썬+주요+용어+정리 20160304
 
일단 시작하는 코틀린
일단 시작하는 코틀린일단 시작하는 코틀린
일단 시작하는 코틀린
 
Programming java day2
Programming java day2Programming java day2
Programming java day2
 
Scala
ScalaScala
Scala
 
UML Diagram about Class / Activity / Object (Korean Language)
UML Diagram about Class / Activity / Object (Korean Language)UML Diagram about Class / Activity / Object (Korean Language)
UML Diagram about Class / Activity / Object (Korean Language)
 
Start IoT with JavaScript - 4.객체1
Start IoT with JavaScript - 4.객체1Start IoT with JavaScript - 4.객체1
Start IoT with JavaScript - 4.객체1
 
[아꿈사] The C++ Programming Language 11장 연산자 오버로딩
[아꿈사] The C++ Programming Language 11장 연산자 오버로딩[아꿈사] The C++ Programming Language 11장 연산자 오버로딩
[아꿈사] The C++ Programming Language 11장 연산자 오버로딩
 

Mais de Nam Hyeonuk

Next 게임 실전 프로젝트 슬라이드
Next 게임 실전 프로젝트 슬라이드Next 게임 실전 프로젝트 슬라이드
Next 게임 실전 프로젝트 슬라이드Nam Hyeonuk
 
Haskell study 15
Haskell study 15Haskell study 15
Haskell study 15Nam Hyeonuk
 
Haskell study 14
Haskell study 14Haskell study 14
Haskell study 14Nam Hyeonuk
 
Haskell study 11
Haskell study 11Haskell study 11
Haskell study 11Nam Hyeonuk
 
Haskell study 10
Haskell study 10Haskell study 10
Haskell study 10Nam Hyeonuk
 
Memory & object pooling
Memory & object poolingMemory & object pooling
Memory & object poolingNam Hyeonuk
 
Iocp 기본 구조 이해
Iocp 기본 구조 이해Iocp 기본 구조 이해
Iocp 기본 구조 이해Nam Hyeonuk
 
Tcp ip & io model
Tcp ip & io modelTcp ip & io model
Tcp ip & io modelNam Hyeonuk
 
Effective c++ chapter 1,2 요약
Effective c++ chapter 1,2 요약Effective c++ chapter 1,2 요약
Effective c++ chapter 1,2 요약Nam Hyeonuk
 
구문과 의미론(정적 의미론까지)
구문과 의미론(정적 의미론까지)구문과 의미론(정적 의미론까지)
구문과 의미론(정적 의미론까지)Nam Hyeonuk
 
Stl vector, list, map
Stl vector, list, mapStl vector, list, map
Stl vector, list, mapNam Hyeonuk
 
Age Of Empires II : Age Of Kings Postmotem
Age Of Empires II : Age Of Kings PostmotemAge Of Empires II : Age Of Kings Postmotem
Age Of Empires II : Age Of Kings PostmotemNam Hyeonuk
 

Mais de Nam Hyeonuk (19)

Next 게임 실전 프로젝트 슬라이드
Next 게임 실전 프로젝트 슬라이드Next 게임 실전 프로젝트 슬라이드
Next 게임 실전 프로젝트 슬라이드
 
Haskell study 15
Haskell study 15Haskell study 15
Haskell study 15
 
Haskell study 14
Haskell study 14Haskell study 14
Haskell study 14
 
Haskell study 11
Haskell study 11Haskell study 11
Haskell study 11
 
Haskell study 10
Haskell study 10Haskell study 10
Haskell study 10
 
Haskell study 7
Haskell study 7Haskell study 7
Haskell study 7
 
Haskell study 0
Haskell study 0Haskell study 0
Haskell study 0
 
Multi thread
Multi threadMulti thread
Multi thread
 
Memory & object pooling
Memory & object poolingMemory & object pooling
Memory & object pooling
 
Database
DatabaseDatabase
Database
 
Exception&log
Exception&logException&log
Exception&log
 
Iocp advanced
Iocp advancedIocp advanced
Iocp advanced
 
Iocp 기본 구조 이해
Iocp 기본 구조 이해Iocp 기본 구조 이해
Iocp 기본 구조 이해
 
Tcp ip & io model
Tcp ip & io modelTcp ip & io model
Tcp ip & io model
 
Effective c++ chapter 1,2 요약
Effective c++ chapter 1,2 요약Effective c++ chapter 1,2 요약
Effective c++ chapter 1,2 요약
 
구문과 의미론(정적 의미론까지)
구문과 의미론(정적 의미론까지)구문과 의미론(정적 의미론까지)
구문과 의미론(정적 의미론까지)
 
Gpg 1.1
Gpg 1.1Gpg 1.1
Gpg 1.1
 
Stl vector, list, map
Stl vector, list, mapStl vector, list, map
Stl vector, list, map
 
Age Of Empires II : Age Of Kings Postmotem
Age Of Empires II : Age Of Kings PostmotemAge Of Empires II : Age Of Kings Postmotem
Age Of Empires II : Age Of Kings Postmotem
 

Haskell study 6

  • 1. Haskell Study 6. type & type class 2
  • 2. Algebraic Data type Haskell에서 새로운 데이터 타입을 정의할 때는 data 키워드를 이용합니다. 표준에서 Bool 데이터 타입은 아래와 같이 선언되어 있습니다. data Bool = False | True data 다음 부분이 타입의 이름이고, = 이후의 부분이 해당 타입의 생성자(값 생성자 - value constructor)를 가리킵니다. | (or)을 이용해 여러 개의 생성자를 만들 수 있습니다. 위의 data 구문은 'Bool 타입은 False 또는 True라는 값 생성자를 가진다' 라는 의미로 볼 수 있습니다. 타입 이름, 값 생성자는 반드시 대문자로 시작해야합니다.
  • 3. Algebraic Data type Haskell에서 어떤 도형에 대한 정보를 나타내고 싶다고 해 봅시다. 예를 들어 원은 중점의 좌표 및 반지름, 사각형은 좌상단과 우하단의 좌표 등으로 표현할 수 있습니다. 이런걸 튜플을 이용해 표현할 수도 있지만, 튜플은 의미를 명확히 파악하기가 쉽지 않기 때문에 새로운 타입을 정의하는 게 좋겠죠. data Shape = Circle Float Float Float | Rectangle Float Float Float Float 위의 예제와 같이 각 값 생성자들은 필드(Field)를 가질 수 있습니다. Circle 값 생성자는 Float형의 값 3가지를 필드로 갖게 되고(첫 두개는 중점, 나머지 하나는 반지름), Rectangle 값 생성자는 Float 형의 값 4가지를 필드로 갖게 되는 거죠(첫 두개는 좌상단, 나머지 두개는 우하단 좌표).
  • 4. Algebraic Data type 값 생성자는 사실 필드의 값이 주어졌을 때 해당 타입의 값을 반환하는 함수라고 볼 수 있습니다. Prelude> :t Circle Circle :: Float -> Float -> Float -> Shape Prelude :t Rectangle Rectangle :: Float -> Float -> Float -> Float -> Shape 그리고 값 생성자는 아래와 같이 해당 타입의 값에 대한 함수의 패턴 매칭에서 사용할 수 있습니다. surface :: Shape -> Float surface (Circle _ _ r) = pi * r ^ 2 surface (Rectangle x1 y1 x2 y2) = abs $ (x2 - x1) * (y2 - y1)
  • 5. Algebraic Data type Bool 타입의 값 생성자 True, False처럼 값 생성자는 필드 값을 가지고 있을 수도 있고 아닐 수도 있습니다. 그리고, 앞에서 봤듯이 값 생성자 역시 함수이기 때문에 커링이 되고, 따라서 부분 적용의 이점을 값 생성자에도 그대로 적용시킬 수 있습니다. {-- 맨 끝에 deriving Show를 붙이면 Show 타입 클래스를 자동으로 상속받게 됩니다. 조금 나중에 다루니 여기서는 일단 "내가 직접 만든 데이터 타입을 결과 창에 띄우려면 deriving Show를 써줘야 한다" 정도로만 이해해주시면 되겠습니다. --} data Shape = Circle Float Float Float | Rectangle Float Float Float Float deriving Show Prelude> map (Circle 10 20) [4,5,6,6] [Circle 10 20 4, Circle 10 20 5, Circle 10 20 6, Circle 10 20 6]
  • 6. Record Syntax 어떤 사람에 대한 정보를 타입으로 나타내고 싶다고 합시다. data Person = Person String String Int String deriving (Show) 첫 두 개는 각각 이름과 성, 세 번째는 나이, 네 번째는 주소라고 합시다. 이제 이 데이터 타입으로부터 각 필드의 값을 가져오려면 아래와 같은 함수들을 만들어야합니다. firstname (Person firstname _ _ _) = firstname lastname (Person _ lastname _ _) = lastname age (Person _ _ age _) = age address (Person _ _ _ address) = address
  • 7. Record Syntax 척 봐도 알겠지만 앞에서처럼 각 필드의 값을 가져오기 위해 일일히 함수를 만들어줘야한다는 것은 굉장히 불편하고 귀찮은 일입니다. Haskell에서는 이런 상황을 위해 Record Syntax라는 문법을 제공합니다. data Person = Person { firstname :: String , lastname :: String , age :: Int , address :: String } deriving (Show) Prelude> let nam = Person "nam" "hyeonuk" 21 "blahblah" Prelude> age nam 21
  • 8. Record Syntax Record syntax는 앞에서와 같이 값 생성자 뒤에 중괄호 ({}), 그 내부에 각 필드의 이름과 타입 어노테이션(::)을 통한 해당 필드의 타입 명시로 이루어져있습니다. Record syntax로 생성된 타입은 각 필드의 값을 가져오는 함수가 자동으로 생성됩니다. Record syntax로 작성된 데이터 타입은 해당 타입의 값 생성자로 값을 만들 때에도 Record syntax 스타일을 사용할 수 있습니다. 이 방식으로 쓸 때에는 반드시 필드의 순서가 선언 순서와 일치할 필요는 없습니다. data Circle = Circle { origin :: (Int, Int) , radius :: Int } deriving (Show) Prelude> let c = Circle { radius = 5, origin = (0,0) } Prelude> origin c (0,0)
  • 9. Type parameter C++의 템플릿과 비슷한 개념으로 Haskell에는 타입 생성자(Type constructor)라는 것이 있습니다. 타입 생성자는 타입을 매개 변수로 받아서 새로운 타입을 만들어냅니다. 표준에 있는 유용한 타입 생성자인 Maybe를 예로 들어봅시다. data Maybe a = Nothing | Just a 여기서 a가 바로 타입 매겨변수입니다. Maybe 타입 생성자는 Nothing 값 생성자가 아니라면 임의의 타입 a에 대해 해당 타입의 값을 하나 필드로 들고 있는 값을 만들어내죠. Maybe Int, Maybe Char같은 것들이 하나의 타입이 되는 겁니다. Maybe Int 타입의 값으로 Just 3, Just 22 같은 게 있을 수 있고, Maybe Char 타입의 값으로 Just 'a', Just 'c'같은 값들이 있을 수 있겠죠.
  • 10. Type parameter 여태껏 써왔던 리스트(list)역시 일종의 타입 매개변수를 받습니다. 여태껏 우리는 임의의 타입에 대한 리스트를 써왔죠. 실제로는 이 리스트 역시 임의의 타입 a에 대해 [a] 타입을 생성하는 타입 생성자를 기반으로 동작하고 있는 것입니다. 타입 매개변수는 내부에 들고 있는 필드의 값이 모든 종류의 값에 대해 일반적으로 동작할 필요가 있을 경우에 사용하면 굉장히 좋습니다.
  • 11. Type synonyms 어떤 타입에 대해 별명을 붙여주고 싶을 때 type 키워드를 사용할 수 있습니다. C언어의 typedef, C++ 11의 using 키워드와 동일한 역할이라고 생각하시면 됩니다. type 키워드는 내부적으로는 완전히 동일하나 이름만 서로 다른 데이터 타입을 만들어냅니다(서로 호환도 됩니다). type 키워드는 코드의 가독성을 위해 사용합니다. 대표적인 예로 String과 [Char]을 들 수 있겠네요. type Point = (Int, Int) distance :: Point -> Point -> Int distance (x1,y1) (x2,y2) = sqrt $ (x2-x1)^2 + (y2-y1)^2
  • 12. Derived instances Haskell의 기본 타입클래스들은 deriving 키워드를 이용해 별도의 정의 없이 해당 타입 클래스의 기본 구현체를 상속받을 수 있습니다. 어떤 타입이 해당 타입 클래스에 정의된 동작을 지원할 때 해당 타입 클래스의 인스턴스(instance)라고 합니다. deriving 키워드를 이용하면 해당 타입 클래스의 동작을 기본적으로 구현하게 됩니다. 앞에서도 봤듯이 deriving Show 를 이용하면 컴파일러가 자동으로 해당 타입이 Show 타입 클래스의 행동을 구현하게 만들어 주죠. Show외에도 Eq, Ord, Enum, Bounded, Show, Read 등에 대해 deriving 키워드를 이용할 수 있습니다. data Person = Person { firstname :: String , lastname :: String , age :: Int } deriving (Show, Eq) Prelude> Person "nam" "hyeonuk" 21 == Person "nam" "hyeonuk" 21 True
  • 13. Recursive Data 데이터 타입은 재귀적인 구조를 가질 수 있습니다. list를 직접 구현해봅시다. data List a = Empty | Cons a (List a) deriving (Show, Read, Eq, Ord) Prelude> 5 `Cons` Empty Cons 5 Empty Prelude> 4 `Cons` 5 `Cons` Empty Cons 4 (Cons 5 Empty) 위의 List 데이터 타입은 Empty(빈 리스트 [])와 Cons(:)라는 두 개의 값 생성자를 가집니다. 그리고 Cons 생성자는 다시 자신의 필드로 List a를 가집니다. 재귀적인 구조가 되는 거죠. 이 재귀적 구조를 이용해서 위와 같이 리스트를 구현할 수 있습니다.
  • 14. Recursive Data 동일한 방식으로 바이너리 트리 역시 구현할 수 있습니다. data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show, Read, Eq) 위 트리구조에 삽입 / 삭제 함수를 적절히 원하는 구조로 작성하면 자신의 필요에 맞게 간단한 Binary Search Tree 등을 구현할 수 있습니다.
  • 15. typeclass 이번엔 직접 타입 클래스를 한 번 만들어봅시다. 우선 예제로 표준에 있는 Eq 타입 클래스가 어떻게 구현되어있는지 먼저 살펴보죠. class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool x == y = not (x /= y) x /= y = not (x == y) 새로운 타입 클래스를 정의하기 위해 class 키워드를 사용합니다. class 뒤에 타입 클래스의 이름과 해당 타입 클래스에 속하는 타입을 지칭하기 위한 타입 매개변수, 그리고 where 이후에 해당 타입 클래스에 속하는 타입들이 수행할 수 있어야만 하는 동작들을 정의합니다.
  • 16. typeclass class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool x == y = not (x /= y) x /= y = not (x == y) 타입 클래스 정의의 맨 아래쪽을 보면 x == y와 x /= y가 서로 재귀적으로 정의되어 있는 것을 볼 수 있습니다. 이 재귀적 정의에 의해 == 또는 /= 둘 중 하나만 정의하면 나머지 하나도 그 정의에 의해 자동으로 정의가 됩니다. 이 덕분에 Eq 타입 클래스에 속하는 타입이 ==과 /= 동작을 어떻게 수행해야할 지 정의할 때 둘 모두를 정의할 필요 없이, 정의하기 편한 것 하나만 정의하면 되는 편의성을 얻을 수 있죠.
  • 17. typeclass 이제 특정 타입이 어떤 타입 클래스의 인스턴스가 되려면 어떻게 해야하는지 정의하는 방법을 살펴봅시다. data TrafficLight = Red | Yellow | Green 신호등 색깔을 나타낸 데이터 타입입니다. 이 타입이 Eq 타입 클래스에 속하게 만들려면 아래와 같이 해야합니다. instance Eq TrafficLight where Red == Red = True Green == Green = True Yellow == Yellow = True _ == _ = False
  • 18. typeclass instance Eq TrafficLight where Red == Red = True Green == Green = True Yellow == Yellow = True _ == _ = False 타입 클래스의 인스턴스를 만들 때는 위와 같이 instance 키워드를 이용합니다. 그리고 원래 타입 매개변수 a로 표현했던 부분에 실제로 인스턴스로 만들고자 하는 타입을 적어주고, where 뒤에 정의해야하는 함수들의 동작을 정의해줍니다. 이 경우 TrafficLight에 대한 == 함수만을 정의해주었고, /= 함수는 재귀적 정의 ( not ( x == y ) )에 의해 자동으로 정의가 됩니다.
  • 19. typeclass 어떤 타입 클래스의 sub typeclass도 만들 수 있습니다. 예를 들어, Ord 타입 클래스는 아래와 같이 정의되어 있습니다. class (Eq a) => Ord a where compare :: a -> a -> Ording ... -- 자세한 구현은 생략 위와 같이 이전에 타입 클래스 제약조건을 표기할 때 썼던 =>을 이용해 sub typeclass를 만들 수 있습니다. 위 선언의 의미는 Ord 타입 클래스에 속하기 위해서는 반드시 Eq 타입 클래스에 먼저 속해야만 한다는 것입니다. 이런 제약은 타입 클래스의 동작을 정의하기 위해 다른 타입 클래스의 동작이 필요한 경우 사용할 수 있습니다.
  • 20. typeclass class (Eq m) => Eq (Maybe m) where Just x == Just y = x == y Nothing == Nothing = True _ == _ = False Maybe 타입의 Eq 타입 클래스 인스턴스 정의입니다. 두 Just 값 비교는 그 내부 값이 같은 지 아닌지로 판별하고 있는데, 이 때 == 함수를 쓰려면 Maybe의 타입 매개변수 역시 Eq 타입 클래스에 속해야만 합니다. 따라서 Eq m 이라는 제약조건을 걸어 Just x 와 Just y 의 비교에 x == y를 사용할 수 있게 만들어야합니다.
  • 21. 연습 문제 • binary search tree BST를 만들어 봅시다. 트리 구조를 저장하기 위한 새로운 타입과, 트리에 원소를 삽입하는 함수, 어떤 원소가 해당 트리에 존재하는지 검색하는 함수 등을 구현해봅시다. BST는 각 노드에 대해 자신의 왼쪽 자식은 모두 자신보다 값이 작아야하며, 자신의 오른쪽자식은 모두 자신보다 값이 큰 트리를 말합니다. 또한 각 노드의 값은 유일해야합니다(중복되는 값이 존재하지 않습니다). 추가적으로 좀 더 연습을 해보고 싶으신 분은 노드를 삭제하는 함수, 혹은 Red-Black Tree나 AVL Tree같이 균형잡인 트리를 만드는 코드를 한 번 작성해보시는 것도 도움이 될 것 같습니다.