SlideShare a Scribd company logo
Haskell
Study
2. list & tuple
List - 표기
list는 Haskell에서 가장 많이 사용되는 자료구조입니다. List는 동일한 타입의 자료를 담는
자료구조이며, 타 언어에서의 링크드 리스트(linked list)와 동일한 내부구조를 갖고 있다고
생각하시면 됩니다. 리스트는 대괄호([]) 및 콤마(,)를 이용하여 표현합니다. ghci를 켜서
확인해봅시다. ghci에서 이름(함수)을 정의하려면 let 키워드를 사용해야합니다. ghci에서 let a = 3
이라고 쓰는 건 스크립트 파일에서 a =3 이라고 쓰고 ghci에서 그 파일을 읽어오는 것과 동일합니다.
Prelude> let numbers = [1,3,5,10,12]
Prelude> numbers
[1,3,5,10,12]
Prelude> let evens = [2,4,6,8,10,12]
Prelude> evens
[2,4,6,8,10,12]
List - 표기
Haskell에서 문자열은 문자들의 리스트와 동일합니다. 각 문자는 홑따옴표(‘) 사이의 문자로
표현되며 문자열은 쌍따옴표(“)사이의 문자들로 표현됩니다. [‘1’,’2’,’3’]과 “123”은 같은
표현입니다.
Prelude> [‘1’,’2’,’3’]
“123”
Prelude> “123”
“123”
List - 표기
두 개의 서로 다른 리스트를 합칠 때는 ++ 연산자를 사용합니다. ++ 연산자를 사용할 때 주의할 점은
이 연산자의 수행 속도가 굉장히 느리다는 것입니다. Haskell의 list는 내부적으로 linked list처럼
동작하기 때문에, ++ 연산자를 사용하면 연산자의 좌측에 있는 모든 원소를 한 번씩 순회하게 됩니다.
리스트에 원소를 추가할 때 사용하는 다른 연산자로 : (cons) 연산자가 있습니다. 이 연산자는
리스트의 맨 앞에 원소 하나를 추가할 때 사용됩니다.
Prelude> “1234” ++ “5678”
“12345678”
Prelude> 0:[1,2,3]
[0,1,2,3]
* 참고) 리스트 [0,1,2,3]은 0:1:2:3:[]과 같은 것입니다.
List - 표기
리스트의 리스트같은 것도 얼마든지 가능합니다. 단, 리스트는 같은 타입의 원소만 담을 수
있으므로 리스트의 리스트같은 경우 내부 리스트들의 타입이 서로 동일해야합니다. 길이는 달라도
상관없습니다.
Prelude> [ [1,2,3] , [1,2] , [5,6,7] ]
[[1,2,3],[1,2],[5,6,7]]
Prelude> [ “apple”, “banana” ]
[“apple”, “banana” ]
Prelude> [ [1,2,3], “apple” ]
<interactive>:4:3:
	 No instance for <Num Char> arising from the literal ‘1’
	 In the expression : 1
	 In the expression : [1,2,3]
	 In the expression : [[1, 2, 3], “apple”]
서로 타입이 다른 리스트를 한
리스트에 넣을 경우 이렇게 에러
메시지가 뜹니다
List - 비교
같은 타입의 두 리스트는 서로 비교할 수 있습니다. 물론 리스트의 원소 타입이 서로 비교될 수 있는
타입이어야합니다. 리스트의 비교의 경우 사전순으로 이루어집니다. 첫번째 원소끼리 비교해서 큰
쪽이 더 크고, 첫번째 원소가 서로 같다면 두번째 원소끼리 비교해서 큰 쪽이 더 크고, ... 하는 식이죠.
Prelude> [1,2,3] > [4,5,6]
False
Prelude> [1,2,3] > [1,2]
True
Prelude> [3,4,2] > [2,4]
True
Prelude> [3,4,2] == [3,4,2]
True
List - 연산
리스트에서 특정 인덱스에 있는 원소의 값을 가져 오고 싶을 때는 !! 연산자를 사용합니다.
Prelude> [1,2,3,4] !! 2
3
head는 리스트의 맨 첫 번째 원소를, tail은 맨 첫 번째 원소를 제외한 나머지 부분의 리스트를
돌려주는 함수입니다.
Prelude> head [1,2,3,4]
1
Prelude> tail [1,2,3,4]
[2,3,4]
List - 연산
last 함수는 리스트의 맨 마지막 원소를, init 함수는 리스트의 마지막 원소를 제외한 나머지 원소들의
리스트를 돌려주는 함수입니다.
Prelude> last [1,2,3,4]
4
Prelude> init [1,2,3,4]
[1,2,3]
아래 그림처럼 생각하시면 편합니다.
[1,2,3,4,5,6,7,8,9,10]
head tail
lastinit
List - 연산
length는 리스트의 길이를 돌려줍니다.
Prelude> length [1,2,3,4]
4
null은 리스트가 텅 비었는지 아닌지 확인해주는 함수입니다. list == [] 와 같은 조건문 보다는 이
함수를 쓰는 편이 편합니다.
Prelude> null [1,2,3,4]
False
Prelude> null []
True
List - 연산
reverse는 리스트를 거꾸로 뒤집어줍니다.
Prelude> reverse [1,2,3,4]
[4,3,2,1]
take는 숫자와 리스트를 인자로 받아 리스트의 시작점부터 해당 개수만큼의 원소로 이루어진
리스트를 반환합니다.
Prelude> take 3 [1,2,3,4]
[1,2,3]
Prelude> take 5 [1,2,3,4]
[1,2,3,4]
List - 연산
drop은 반대로 주어진 개수만큼의 원소를 리스트의 시작점부터 제거합니다.
Prelude> drop 3 [1,2,3,4]
[4]
Prelude> drop 5 [1,2,3,4]
[]
maximum / minimum은 각각 리스트의 최댓값과 최솟값을 반환합니다.
Prelude> maximum [1,2,3,4]
4
Prelude> minimum [1,2,3,4]
1
List - 연산
sum / product는 각각 리스트의 원소들 모두를 더한 값과 모두를 곱한 값을 반환합니다.
Prelude> sum [1,2,3,4]
10
Prelude> product [1,2,3,4]
24
elem은 원소 하나와 리스트를 받아서 해당 원소가 리스트에 포함되는지 아닌지 여부를 판별해줍니다.
Prelude> ‘a’ `elem` “abcd”
True
Prelude> 3 `elem` [1,2,4,5]
False
List - 범위
Haskell에는 특정 범위에 있는 값들의 리스트를 만들고 싶을 때 사용할 수 있는 좋은 문법이 있습니다.
범위(range) 리스트는 특정 범위에 있는 등차 수열을 쉽게 만들어냅니다.
Prelude> [1..10]
[1,2,3,4,5,6,7,8,9,10]
기본적으로 [(시작값)..(종료값)] 형태의 문법을 갖고 있으며 이런 형태의 리스트는 시작값에서 값을
하나씩 증가시키며 종료값까지의 모든 원소들을 포함하는 리스트를 생성합니다.
Prelude> [‘a’..’z’]
“abcdefghijklmnopqrstuvwxyz”
Prelude> [‘A’..’F’]
“ABCDEF”
List - 범위
값의 증가 정도를 바꾸고 싶다면 첫번째 원소와 두번째 원소까지 표기해주면 됩니다. 이렇게 할 경우
두 원소의 차이만큼 값을 증가시키며 주어진 범위 내의 원소들로 이루어진 리스트를 만들어줍니다.
Prelude> [1,4..10]
[1,4,7,10]
Prelude> [‘a’,’c’..’z’]
“acegikmoqsuwy”
Prelude> [0.1, 0.3 .. 1]
[0.1,0.3,0.5,0.7,0.899999999999,1.0999999999999]
부동 소수점의 경우 위 예제처럼 부정확한 결과가 나올 수 있으므로 이 문법에서는 부동 소수점은
되도록 안 쓰는 것이 좋습니다.
List - 범위:무한
Haskell은 지연 계산이라는 특징을 이용해서 무한대 크기의 리스트를 만들어낼 수 있습니다. 앞의
범위 리스트에서 마지막 값을 생략하면 곧 무한대 크기의 리스트가 됩니다. 예를 들어 짝수들의
리스트를 생각해봅시다.
Prelude> let evens = [2,4..]
이제 evens는 짝수들의 리스트입니다. 이렇게 evens를 정의하는 시점까지는 지연 계산의
특성때문에 해당 식을 계산하지 않습니다. 이제 처음부터 10개의 짝수를 가져와봅시다.
Prelude> take 10 evens
[2,4,6,8,10,12,14,16,18,20]
무한대 크기의 리스트는 유용하게 사용될 수 있습니다. 무한대 리스트와 관련된 함수를 살펴봅시다.
List - 범위:무한
cycle 함수는 리스트를 인자로 받아 그 리스트의 원소를 무한히 반복하는 리스트를 만들어냅니다.
Prelude> take 10 (cycle [1,2,3])
[1,2,3,1,2,3,1,2,3,1]
Prelude> take 12 (cycle “EE! “)
“EE! EE! EE! “
repeat는 원소를 하나 받아서 그 원소로만 이루어진 무한대 크기의 리스트를 만듭니다.
Prelude> take 5 (repeat 3)
[3,3,3,3,3]
take n (repeat k)는 replicate n k와 같습니다. 위 예제의 경우 보통 replicate 5 3과 같이 씁니다.
List Comprehension
list comprehension은 list를 만들 때 굉장히 유용하게 사용될 수 있는 문법입니다. 이 문법은
수학에서 집합을 표기할 때 사용하는 조건제시법과 아주 비슷합니다. 가장 처음 10개의 짝수를
나타내는 리스트를 list comprehension을 이용해 표기해봅시다.
Prelude> [x*2 | x <- [1..10]]
[2,4,6,8,10,12,14,16,18,20]
list comprehension에서 파이프(|) 왼쪽은 결과 리스트에 들어갈 원소를 나타내고, 파이프
오른쪽은 그 원소를 구하기 위한 여러가지 조건들을 의미합니다. 위 코드에서 x <- [1..10]을 통해 x
는 리스트 [1..10] 속에 속하는 원소임을 나타내고, 그 각각의 x에 대해 2를 곱한 값이 결과 리스트에
포함된다고 표기했으므로 최종적으로 첫 10개의 짝수 리스트를 얻게 됩니다.
List Comprehension
몇 가지 예제를 더 살펴봅시다. 우선, 첫 10개의 짝수 중에서 크기가 10이상인 짝수들의 리스트를
list comprehension을 통해 구해봅시다. 이를 위해서 파이프(|) 오른쪽에 조건(술어)를 더해줄 수
있습니다.
Prelude> [x*2 | x <- [1..10], x*2 >= 10]
[10,12,14,16,18,20]
1부터 20 사이의 숫자중 3 또는 5의 배수는 어떻게 구할 수 있을까요?
Prelude> [x | x <- [1..20], x `mod` 3 == 0 || x `mod` 5 == 0]
[3,5,6,9,10,12,15,18,20]
List Comprehension
list comprehension에서 술어를 여러 개 줄 수도 있으며, 한 번에 여러 개의 리스트로부터 원소를
가져올 수도 있습니다. 예를 들어서, [1,2,3]과 [4,5,6]의 모든 원소들의 곱으로 이루어진 원소를
만들고 싶다고 해 봅시다.
Prelude> [x*y | x <- [1,2,3], y <- [4,5,6] ]
[4,5,6,8,10,12,12,15,18]
Prelude> [x*y | x <- [1,2,3], y <- [4,5,6], x*y > 10]
[12,12,15,18]
이건 마치 명령형 언어에서 이중 반복문처럼 동작합니다. [1,2,3]에서 원소들을 하나씩 꺼내고, 그
원소 각각에 대해 y의 모든 원소들을 대응시키면서 모든 경우의 수를 테스트해봅니다.
List Comprehension
list comprehension 역시 중첩해서 사용할 수 있습니다. 예를 들어 list의 list에서 내부의 list들에
대해 짝수인 원소들은 모두 제거하고 싶다고 해 봅시다.
first.hs
removeOdd xxs = [ [ x | x <- xs, odd x] | xs <- xxs]
ghci
Prelude> :l first.hs
Prelude> removeOdd [[1,2,3,4], [5,6,7,8], [2,4,6,8], [1,3,5,7]]
[[1,3],[5,7],[],[1,3,5,7]]
list comprehension은 중첩해서 쓸 경우 가독성이 별로 좋지 않습니다. 이럴 땐 여러 줄에 나눠서
쓰거나 다른 방식으로 문제를 해결하는 걸 고민해보시는 게 좋습니다.
연습 문제
•	lastButOne
list가 주어지면 해당 리스트의 마지막에서 한 칸 앞 원소를 리턴하는 함수를 작성해봅시다. 예를 들어
lastButOne [1,2,3,4]는 3을 리턴해야합니다.
•	notCapital
문자열이 주어졌을 때 해당 문자열에서 대문자를 제거한 문자열을 리턴하는 함수를 작성해봅시다.
예를 들어 notCapital “HaHaHa, NotCapital” 은 “aaa, otapital”을 리턴해야합니다.
•	diff
두 개의 리스트 a,b가 주어졌을 때 a의 원소 중 b에 포함되지 않는 원소로만 구성된 리스트를 리턴하는
함수를 작성해봅시다. 예를 들어 diff [1,2,3,4,5,6] [3,5,7] 은 [1,2,4,6]을 리턴해야합니다.
tuple
tuple은 list와 비슷하게 여러 개의 값을 담는 자료구조입니다. tuple이 list와 차이 나는 두 가지는,
tuple은 원소 개수가 고정이며 서로 다른 타입의 값도 담을 수 있다는 것입니다. tuple은 소괄호와
콤마로 구성됩니다. 튜플은 수학에서 벡터 등을 표기하는데 굉장히 유용하게 사용될 수 있습니다.
튜플의 한 가지 특징은 원소 개수가 다르면 서로 다른 타입이라는 것입니다.
Prelude> [(1,2), (1,2,3)]
<interactive>:2:9:
	 Couldn’t match expected type ‘(t, t3)’
				 with actual type ‘(t0, t1, t2)’
	 Relevant bindings include
		 it :: [(t, t3)] (bound at <interactive>:2:1)
	 In the expression: (1,2,3)
	 In the expression: [(1,2), (1,2,3)]
	 In an equation for ‘it’ : it = [(1,2), (1,2,3)]
이렇게 서로 다른
타입을 한 리스트에
담을 수 없다는 에러
메시지가 발생합니다.
tuple
튜플은 수학에서의 2차원, 3차원 벡터 등을 표기할 때나, 서로 다른 타입의 값 몇 가지를 묶어서
관리할 필요가 있을 때 굉장히 유용하게 사용됩니다. 일반적으로 크기가 2인 튜플을 페어(pair), 3인
튜플을 트리플(triple)이라고 부릅니다. 페어의 경우 fst와 snd 함수가 유용합니다.
Prelude> fst (1,4)
1
Prelude> snd (1,4)
4
fst와 snd 함수는 크기가 2인 튜플에서만 사용가능합니다. 3-tuple, 4-tuple, ... 등에 대해서는
동작하지 않습니다. 이런 다양한 크기의 튜플에 대해 각 원소들을 뽑아내는 방법은 다음에 다뤄봅시다.
tuple
pair들의 리스트를 만들어내는 zip이라는 굉장히 유용한 함수가 있습니다. 이 함수는 두 개의
리스트를 인자로 받아 두 리스트의 원소를 하나씩 짝 지은 페어들의 리스트를 반환합니다.
Prelude> zip [‘one’, ‘two’, ‘three’] [1,2,3]
[(‘one’,1), (‘two’,2), (‘three’,3)]
Prelude> zip [1..] “abcd”
[(1,’a’), (2,’b’), (3,’c’), (4,’d’)]
zip은 두 개의 리스트를 하나로 합치거나 두 리스트를 동시에 순회해야할 때 유용하게 사용할 수
있습니다. zip의 인자로 들어온 두 리스트의 길이가 서로 다를 경우 길이가 짧은 쪽의 리스트에 맞춰서
잘립니다.
활용
tuple과 list를 이용해서 다음 문제를 풀어봅시다.
“세 변의 길이가 모두 10이하의 정수인 삼각형 중에서, 둘레가 24인 직각 삼각형에는 어떤 것이
있는가?”
이 문제는 list comprehension과 tuple을 이용하면 굉장히 쉽게 풀 수 있습니다. 우선 list
comprehension을 이용해 세 변의 길이가 모두 10이하인 삼각형 목록을 구해봅시다.
[(a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10]]
활용
여기서 직각 삼각형의 경우 빗변 길이의 제곱은 나머지 두 변의 길이의 제곱의 합과 같으며,
직각삼각형의 각 변은 빗변의 길이보다 길 수 없다는 조건을 반영해봅시다.
[(a,b,c) | c <- [1..10], b <- [1..c], a <- [1..b],
a^2 + b^2 == c^2]
이제 우리가 고려하지 않은 조건은 둘레가 24라는 조건 하나뿐입니다. 이 조건 하나까지 반영해서
답을 구해 봅시다.
Prelude> [(a,b,c)| c <- [1..10], b <- [1..c], a <- [1..b],
a^2 + b^2 == c^2, a+b+c==24]
[(6,8,10)]
연습 문제
•	swap
페어의 리스트를 받아서 리스트의 모든 원소를 순서를 바꾸는 함수를 만들어봅시다. 예를 들어
swap [(1,2), (3,4), (5,6), (7,8)]은 [(2,1), (4,3), (6,5), (8,7)]을 리턴해야합니다.
•	sum
리스트를 받아서 리스트의 모든 원소의 합을 구하는 함수를 만들어봅시다. 이미 표준 라이브러리에
존재하는 함수니 sum 외의 다른 이름으로 작성하셔야합니다. 예를 들어 sum’ [1,2,3,4,5] 는 15를
리턴해야합니다.
•	divisors
숫자 하나를 받아 그 숫자의 모든 약수 리스트를 리턴하는 함수를 만들어봅시다. 예를 들어
divisors 20 은 [1,2,4,5,10,20]을 리턴해야합니다.

More Related Content

PDF
Haskell study 1
Nam Hyeonuk
 
PDF
Haskell study 4
Nam Hyeonuk
 
PDF
Haskell study 5
Nam Hyeonuk
 
PDF
Haskell study 3
Nam Hyeonuk
 
PDF
Haskell study 6
Nam Hyeonuk
 
PDF
Haskell study 9
Nam Hyeonuk
 
PDF
Haskell study 12
Nam Hyeonuk
 
PDF
Haskell study 13
Nam Hyeonuk
 
Haskell study 1
Nam Hyeonuk
 
Haskell study 4
Nam Hyeonuk
 
Haskell study 5
Nam Hyeonuk
 
Haskell study 3
Nam Hyeonuk
 
Haskell study 6
Nam Hyeonuk
 
Haskell study 9
Nam Hyeonuk
 
Haskell study 12
Nam Hyeonuk
 
Haskell study 13
Nam Hyeonuk
 

What's hot (20)

PDF
Haskell study 8
Nam Hyeonuk
 
PDF
Haskell study 15
Nam Hyeonuk
 
PDF
Kleisli Composition
Philip Schwarz
 
PDF
Tema 6: Definiciones por recursión en Haskell
José A. Alonso
 
PPTX
Servlets - filter, listeners, wrapper, internationalization
susant sahu
 
PDF
SQL BASIC QUERIES SOLUTION ~hmftj
LGS, GBHS&IC, University Of South-Asia, TARA-Technologies
 
PDF
The Functional Programming Triad of Map, Filter and Fold
Philip Schwarz
 
PDF
Arriving at monads by going from pure-function composition to effectful-funct...
Philip Schwarz
 
PDF
ZIO Queue
John De Goes
 
PDF
Collections Api - Java
Drishti Bhalla
 
PPT
SQL subquery
Vikas Gupta
 
PPT
Lisp Programming Languge
Yaser Jaradeh
 
PDF
The aggregate function - from sequential and parallel folds to parallel aggre...
Philip Schwarz
 
PDF
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Philip Schwarz
 
PDF
Spring I/O 2012: Natural Templating in Spring MVC with Thymeleaf
Thymeleaf
 
PDF
Sierpinski Triangle - Polyglot FP for Fun and Profit - Haskell and Scala
Philip Schwarz
 
PDF
Arrays in PHP
Vineet Kumar Saini
 
PDF
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
John De Goes
 
PDF
스프링 시큐리티 구조 이해
beom kyun choi
 
DOCX
系統程式 -- 附錄
鍾誠 陳鍾誠
 
Haskell study 8
Nam Hyeonuk
 
Haskell study 15
Nam Hyeonuk
 
Kleisli Composition
Philip Schwarz
 
Tema 6: Definiciones por recursión en Haskell
José A. Alonso
 
Servlets - filter, listeners, wrapper, internationalization
susant sahu
 
The Functional Programming Triad of Map, Filter and Fold
Philip Schwarz
 
Arriving at monads by going from pure-function composition to effectful-funct...
Philip Schwarz
 
ZIO Queue
John De Goes
 
Collections Api - Java
Drishti Bhalla
 
SQL subquery
Vikas Gupta
 
Lisp Programming Languge
Yaser Jaradeh
 
The aggregate function - from sequential and parallel folds to parallel aggre...
Philip Schwarz
 
Algebraic Data Types for Data Oriented Programming - From Haskell and Scala t...
Philip Schwarz
 
Spring I/O 2012: Natural Templating in Spring MVC with Thymeleaf
Thymeleaf
 
Sierpinski Triangle - Polyglot FP for Fun and Profit - Haskell and Scala
Philip Schwarz
 
Arrays in PHP
Vineet Kumar Saini
 
Blazing Fast, Pure Effects without Monads — LambdaConf 2018
John De Goes
 
스프링 시큐리티 구조 이해
beom kyun choi
 
系統程式 -- 附錄
鍾誠 陳鍾誠
 
Ad

Similar to Haskell study 2 (20)

PDF
Python3 10장 문자열이야기
Jihoon Kong
 
PPTX
파이썬 문자열 이해하기
Yong Joon Moon
 
PPTX
파이썬 문자열 이해하기
Yong Joon Moon
 
PPTX
파이썬정리 20160130
Yong Joon Moon
 
PPTX
Apply교육
Kangwook Lee
 
PDF
Scala 기초 (4)
명성 정
 
PDF
R 기초 : R Basics
Yoonwhan Lee
 
PPTX
Data Mining with R CH1 요약
Sung Yub Kim
 
PDF
Stl vector, list, map
Nam Hyeonuk
 
PPTX
R 프로그래밍-향상된 데이타 조작
Terry Cho
 
PDF
파이썬 기본 문법
SeongHyun Ahn
 
PDF
[D2 CAMPUS] 부산대 Alcall 프로그래밍 경시대회 문제 풀이
NAVER D2
 
PDF
[Algorithm] Selection Sort
Bill Kim
 
PDF
Start IoT with JavaScript - 4.객체1
Park Jonggun
 
DOCX
이산치수학 Project3
KoChungWook
 
PPT
Erlang을 이용한 swap 서버
Jaejin Yun
 
PDF
STL study (skyLab)
Gyeongwook Choi
 
PPTX
텐서플로우-기초 프로그래밍
jdo
 
PPTX
Swift 튜플 (tuples)
주원 김
 
PDF
파이썬 자료형 발표
joonjhokil
 
Python3 10장 문자열이야기
Jihoon Kong
 
파이썬 문자열 이해하기
Yong Joon Moon
 
파이썬 문자열 이해하기
Yong Joon Moon
 
파이썬정리 20160130
Yong Joon Moon
 
Apply교육
Kangwook Lee
 
Scala 기초 (4)
명성 정
 
R 기초 : R Basics
Yoonwhan Lee
 
Data Mining with R CH1 요약
Sung Yub Kim
 
Stl vector, list, map
Nam Hyeonuk
 
R 프로그래밍-향상된 데이타 조작
Terry Cho
 
파이썬 기본 문법
SeongHyun Ahn
 
[D2 CAMPUS] 부산대 Alcall 프로그래밍 경시대회 문제 풀이
NAVER D2
 
[Algorithm] Selection Sort
Bill Kim
 
Start IoT with JavaScript - 4.객체1
Park Jonggun
 
이산치수학 Project3
KoChungWook
 
Erlang을 이용한 swap 서버
Jaejin Yun
 
STL study (skyLab)
Gyeongwook Choi
 
텐서플로우-기초 프로그래밍
jdo
 
Swift 튜플 (tuples)
주원 김
 
파이썬 자료형 발표
joonjhokil
 
Ad

More from Nam Hyeonuk (17)

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

Haskell study 2

  • 2. List - 표기 list는 Haskell에서 가장 많이 사용되는 자료구조입니다. List는 동일한 타입의 자료를 담는 자료구조이며, 타 언어에서의 링크드 리스트(linked list)와 동일한 내부구조를 갖고 있다고 생각하시면 됩니다. 리스트는 대괄호([]) 및 콤마(,)를 이용하여 표현합니다. ghci를 켜서 확인해봅시다. ghci에서 이름(함수)을 정의하려면 let 키워드를 사용해야합니다. ghci에서 let a = 3 이라고 쓰는 건 스크립트 파일에서 a =3 이라고 쓰고 ghci에서 그 파일을 읽어오는 것과 동일합니다. Prelude> let numbers = [1,3,5,10,12] Prelude> numbers [1,3,5,10,12] Prelude> let evens = [2,4,6,8,10,12] Prelude> evens [2,4,6,8,10,12]
  • 3. List - 표기 Haskell에서 문자열은 문자들의 리스트와 동일합니다. 각 문자는 홑따옴표(‘) 사이의 문자로 표현되며 문자열은 쌍따옴표(“)사이의 문자들로 표현됩니다. [‘1’,’2’,’3’]과 “123”은 같은 표현입니다. Prelude> [‘1’,’2’,’3’] “123” Prelude> “123” “123”
  • 4. List - 표기 두 개의 서로 다른 리스트를 합칠 때는 ++ 연산자를 사용합니다. ++ 연산자를 사용할 때 주의할 점은 이 연산자의 수행 속도가 굉장히 느리다는 것입니다. Haskell의 list는 내부적으로 linked list처럼 동작하기 때문에, ++ 연산자를 사용하면 연산자의 좌측에 있는 모든 원소를 한 번씩 순회하게 됩니다. 리스트에 원소를 추가할 때 사용하는 다른 연산자로 : (cons) 연산자가 있습니다. 이 연산자는 리스트의 맨 앞에 원소 하나를 추가할 때 사용됩니다. Prelude> “1234” ++ “5678” “12345678” Prelude> 0:[1,2,3] [0,1,2,3] * 참고) 리스트 [0,1,2,3]은 0:1:2:3:[]과 같은 것입니다.
  • 5. List - 표기 리스트의 리스트같은 것도 얼마든지 가능합니다. 단, 리스트는 같은 타입의 원소만 담을 수 있으므로 리스트의 리스트같은 경우 내부 리스트들의 타입이 서로 동일해야합니다. 길이는 달라도 상관없습니다. Prelude> [ [1,2,3] , [1,2] , [5,6,7] ] [[1,2,3],[1,2],[5,6,7]] Prelude> [ “apple”, “banana” ] [“apple”, “banana” ] Prelude> [ [1,2,3], “apple” ] <interactive>:4:3: No instance for <Num Char> arising from the literal ‘1’ In the expression : 1 In the expression : [1,2,3] In the expression : [[1, 2, 3], “apple”] 서로 타입이 다른 리스트를 한 리스트에 넣을 경우 이렇게 에러 메시지가 뜹니다
  • 6. List - 비교 같은 타입의 두 리스트는 서로 비교할 수 있습니다. 물론 리스트의 원소 타입이 서로 비교될 수 있는 타입이어야합니다. 리스트의 비교의 경우 사전순으로 이루어집니다. 첫번째 원소끼리 비교해서 큰 쪽이 더 크고, 첫번째 원소가 서로 같다면 두번째 원소끼리 비교해서 큰 쪽이 더 크고, ... 하는 식이죠. Prelude> [1,2,3] > [4,5,6] False Prelude> [1,2,3] > [1,2] True Prelude> [3,4,2] > [2,4] True Prelude> [3,4,2] == [3,4,2] True
  • 7. List - 연산 리스트에서 특정 인덱스에 있는 원소의 값을 가져 오고 싶을 때는 !! 연산자를 사용합니다. Prelude> [1,2,3,4] !! 2 3 head는 리스트의 맨 첫 번째 원소를, tail은 맨 첫 번째 원소를 제외한 나머지 부분의 리스트를 돌려주는 함수입니다. Prelude> head [1,2,3,4] 1 Prelude> tail [1,2,3,4] [2,3,4]
  • 8. List - 연산 last 함수는 리스트의 맨 마지막 원소를, init 함수는 리스트의 마지막 원소를 제외한 나머지 원소들의 리스트를 돌려주는 함수입니다. Prelude> last [1,2,3,4] 4 Prelude> init [1,2,3,4] [1,2,3] 아래 그림처럼 생각하시면 편합니다. [1,2,3,4,5,6,7,8,9,10] head tail lastinit
  • 9. List - 연산 length는 리스트의 길이를 돌려줍니다. Prelude> length [1,2,3,4] 4 null은 리스트가 텅 비었는지 아닌지 확인해주는 함수입니다. list == [] 와 같은 조건문 보다는 이 함수를 쓰는 편이 편합니다. Prelude> null [1,2,3,4] False Prelude> null [] True
  • 10. List - 연산 reverse는 리스트를 거꾸로 뒤집어줍니다. Prelude> reverse [1,2,3,4] [4,3,2,1] take는 숫자와 리스트를 인자로 받아 리스트의 시작점부터 해당 개수만큼의 원소로 이루어진 리스트를 반환합니다. Prelude> take 3 [1,2,3,4] [1,2,3] Prelude> take 5 [1,2,3,4] [1,2,3,4]
  • 11. List - 연산 drop은 반대로 주어진 개수만큼의 원소를 리스트의 시작점부터 제거합니다. Prelude> drop 3 [1,2,3,4] [4] Prelude> drop 5 [1,2,3,4] [] maximum / minimum은 각각 리스트의 최댓값과 최솟값을 반환합니다. Prelude> maximum [1,2,3,4] 4 Prelude> minimum [1,2,3,4] 1
  • 12. List - 연산 sum / product는 각각 리스트의 원소들 모두를 더한 값과 모두를 곱한 값을 반환합니다. Prelude> sum [1,2,3,4] 10 Prelude> product [1,2,3,4] 24 elem은 원소 하나와 리스트를 받아서 해당 원소가 리스트에 포함되는지 아닌지 여부를 판별해줍니다. Prelude> ‘a’ `elem` “abcd” True Prelude> 3 `elem` [1,2,4,5] False
  • 13. List - 범위 Haskell에는 특정 범위에 있는 값들의 리스트를 만들고 싶을 때 사용할 수 있는 좋은 문법이 있습니다. 범위(range) 리스트는 특정 범위에 있는 등차 수열을 쉽게 만들어냅니다. Prelude> [1..10] [1,2,3,4,5,6,7,8,9,10] 기본적으로 [(시작값)..(종료값)] 형태의 문법을 갖고 있으며 이런 형태의 리스트는 시작값에서 값을 하나씩 증가시키며 종료값까지의 모든 원소들을 포함하는 리스트를 생성합니다. Prelude> [‘a’..’z’] “abcdefghijklmnopqrstuvwxyz” Prelude> [‘A’..’F’] “ABCDEF”
  • 14. List - 범위 값의 증가 정도를 바꾸고 싶다면 첫번째 원소와 두번째 원소까지 표기해주면 됩니다. 이렇게 할 경우 두 원소의 차이만큼 값을 증가시키며 주어진 범위 내의 원소들로 이루어진 리스트를 만들어줍니다. Prelude> [1,4..10] [1,4,7,10] Prelude> [‘a’,’c’..’z’] “acegikmoqsuwy” Prelude> [0.1, 0.3 .. 1] [0.1,0.3,0.5,0.7,0.899999999999,1.0999999999999] 부동 소수점의 경우 위 예제처럼 부정확한 결과가 나올 수 있으므로 이 문법에서는 부동 소수점은 되도록 안 쓰는 것이 좋습니다.
  • 15. List - 범위:무한 Haskell은 지연 계산이라는 특징을 이용해서 무한대 크기의 리스트를 만들어낼 수 있습니다. 앞의 범위 리스트에서 마지막 값을 생략하면 곧 무한대 크기의 리스트가 됩니다. 예를 들어 짝수들의 리스트를 생각해봅시다. Prelude> let evens = [2,4..] 이제 evens는 짝수들의 리스트입니다. 이렇게 evens를 정의하는 시점까지는 지연 계산의 특성때문에 해당 식을 계산하지 않습니다. 이제 처음부터 10개의 짝수를 가져와봅시다. Prelude> take 10 evens [2,4,6,8,10,12,14,16,18,20] 무한대 크기의 리스트는 유용하게 사용될 수 있습니다. 무한대 리스트와 관련된 함수를 살펴봅시다.
  • 16. List - 범위:무한 cycle 함수는 리스트를 인자로 받아 그 리스트의 원소를 무한히 반복하는 리스트를 만들어냅니다. Prelude> take 10 (cycle [1,2,3]) [1,2,3,1,2,3,1,2,3,1] Prelude> take 12 (cycle “EE! “) “EE! EE! EE! “ repeat는 원소를 하나 받아서 그 원소로만 이루어진 무한대 크기의 리스트를 만듭니다. Prelude> take 5 (repeat 3) [3,3,3,3,3] take n (repeat k)는 replicate n k와 같습니다. 위 예제의 경우 보통 replicate 5 3과 같이 씁니다.
  • 17. List Comprehension list comprehension은 list를 만들 때 굉장히 유용하게 사용될 수 있는 문법입니다. 이 문법은 수학에서 집합을 표기할 때 사용하는 조건제시법과 아주 비슷합니다. 가장 처음 10개의 짝수를 나타내는 리스트를 list comprehension을 이용해 표기해봅시다. Prelude> [x*2 | x <- [1..10]] [2,4,6,8,10,12,14,16,18,20] list comprehension에서 파이프(|) 왼쪽은 결과 리스트에 들어갈 원소를 나타내고, 파이프 오른쪽은 그 원소를 구하기 위한 여러가지 조건들을 의미합니다. 위 코드에서 x <- [1..10]을 통해 x 는 리스트 [1..10] 속에 속하는 원소임을 나타내고, 그 각각의 x에 대해 2를 곱한 값이 결과 리스트에 포함된다고 표기했으므로 최종적으로 첫 10개의 짝수 리스트를 얻게 됩니다.
  • 18. List Comprehension 몇 가지 예제를 더 살펴봅시다. 우선, 첫 10개의 짝수 중에서 크기가 10이상인 짝수들의 리스트를 list comprehension을 통해 구해봅시다. 이를 위해서 파이프(|) 오른쪽에 조건(술어)를 더해줄 수 있습니다. Prelude> [x*2 | x <- [1..10], x*2 >= 10] [10,12,14,16,18,20] 1부터 20 사이의 숫자중 3 또는 5의 배수는 어떻게 구할 수 있을까요? Prelude> [x | x <- [1..20], x `mod` 3 == 0 || x `mod` 5 == 0] [3,5,6,9,10,12,15,18,20]
  • 19. List Comprehension list comprehension에서 술어를 여러 개 줄 수도 있으며, 한 번에 여러 개의 리스트로부터 원소를 가져올 수도 있습니다. 예를 들어서, [1,2,3]과 [4,5,6]의 모든 원소들의 곱으로 이루어진 원소를 만들고 싶다고 해 봅시다. Prelude> [x*y | x <- [1,2,3], y <- [4,5,6] ] [4,5,6,8,10,12,12,15,18] Prelude> [x*y | x <- [1,2,3], y <- [4,5,6], x*y > 10] [12,12,15,18] 이건 마치 명령형 언어에서 이중 반복문처럼 동작합니다. [1,2,3]에서 원소들을 하나씩 꺼내고, 그 원소 각각에 대해 y의 모든 원소들을 대응시키면서 모든 경우의 수를 테스트해봅니다.
  • 20. List Comprehension list comprehension 역시 중첩해서 사용할 수 있습니다. 예를 들어 list의 list에서 내부의 list들에 대해 짝수인 원소들은 모두 제거하고 싶다고 해 봅시다. first.hs removeOdd xxs = [ [ x | x <- xs, odd x] | xs <- xxs] ghci Prelude> :l first.hs Prelude> removeOdd [[1,2,3,4], [5,6,7,8], [2,4,6,8], [1,3,5,7]] [[1,3],[5,7],[],[1,3,5,7]] list comprehension은 중첩해서 쓸 경우 가독성이 별로 좋지 않습니다. 이럴 땐 여러 줄에 나눠서 쓰거나 다른 방식으로 문제를 해결하는 걸 고민해보시는 게 좋습니다.
  • 21. 연습 문제 • lastButOne list가 주어지면 해당 리스트의 마지막에서 한 칸 앞 원소를 리턴하는 함수를 작성해봅시다. 예를 들어 lastButOne [1,2,3,4]는 3을 리턴해야합니다. • notCapital 문자열이 주어졌을 때 해당 문자열에서 대문자를 제거한 문자열을 리턴하는 함수를 작성해봅시다. 예를 들어 notCapital “HaHaHa, NotCapital” 은 “aaa, otapital”을 리턴해야합니다. • diff 두 개의 리스트 a,b가 주어졌을 때 a의 원소 중 b에 포함되지 않는 원소로만 구성된 리스트를 리턴하는 함수를 작성해봅시다. 예를 들어 diff [1,2,3,4,5,6] [3,5,7] 은 [1,2,4,6]을 리턴해야합니다.
  • 22. tuple tuple은 list와 비슷하게 여러 개의 값을 담는 자료구조입니다. tuple이 list와 차이 나는 두 가지는, tuple은 원소 개수가 고정이며 서로 다른 타입의 값도 담을 수 있다는 것입니다. tuple은 소괄호와 콤마로 구성됩니다. 튜플은 수학에서 벡터 등을 표기하는데 굉장히 유용하게 사용될 수 있습니다. 튜플의 한 가지 특징은 원소 개수가 다르면 서로 다른 타입이라는 것입니다. Prelude> [(1,2), (1,2,3)] <interactive>:2:9: Couldn’t match expected type ‘(t, t3)’ with actual type ‘(t0, t1, t2)’ Relevant bindings include it :: [(t, t3)] (bound at <interactive>:2:1) In the expression: (1,2,3) In the expression: [(1,2), (1,2,3)] In an equation for ‘it’ : it = [(1,2), (1,2,3)] 이렇게 서로 다른 타입을 한 리스트에 담을 수 없다는 에러 메시지가 발생합니다.
  • 23. tuple 튜플은 수학에서의 2차원, 3차원 벡터 등을 표기할 때나, 서로 다른 타입의 값 몇 가지를 묶어서 관리할 필요가 있을 때 굉장히 유용하게 사용됩니다. 일반적으로 크기가 2인 튜플을 페어(pair), 3인 튜플을 트리플(triple)이라고 부릅니다. 페어의 경우 fst와 snd 함수가 유용합니다. Prelude> fst (1,4) 1 Prelude> snd (1,4) 4 fst와 snd 함수는 크기가 2인 튜플에서만 사용가능합니다. 3-tuple, 4-tuple, ... 등에 대해서는 동작하지 않습니다. 이런 다양한 크기의 튜플에 대해 각 원소들을 뽑아내는 방법은 다음에 다뤄봅시다.
  • 24. tuple pair들의 리스트를 만들어내는 zip이라는 굉장히 유용한 함수가 있습니다. 이 함수는 두 개의 리스트를 인자로 받아 두 리스트의 원소를 하나씩 짝 지은 페어들의 리스트를 반환합니다. Prelude> zip [‘one’, ‘two’, ‘three’] [1,2,3] [(‘one’,1), (‘two’,2), (‘three’,3)] Prelude> zip [1..] “abcd” [(1,’a’), (2,’b’), (3,’c’), (4,’d’)] zip은 두 개의 리스트를 하나로 합치거나 두 리스트를 동시에 순회해야할 때 유용하게 사용할 수 있습니다. zip의 인자로 들어온 두 리스트의 길이가 서로 다를 경우 길이가 짧은 쪽의 리스트에 맞춰서 잘립니다.
  • 25. 활용 tuple과 list를 이용해서 다음 문제를 풀어봅시다. “세 변의 길이가 모두 10이하의 정수인 삼각형 중에서, 둘레가 24인 직각 삼각형에는 어떤 것이 있는가?” 이 문제는 list comprehension과 tuple을 이용하면 굉장히 쉽게 풀 수 있습니다. 우선 list comprehension을 이용해 세 변의 길이가 모두 10이하인 삼각형 목록을 구해봅시다. [(a,b,c) | c <- [1..10], b <- [1..10], a <- [1..10]]
  • 26. 활용 여기서 직각 삼각형의 경우 빗변 길이의 제곱은 나머지 두 변의 길이의 제곱의 합과 같으며, 직각삼각형의 각 변은 빗변의 길이보다 길 수 없다는 조건을 반영해봅시다. [(a,b,c) | c <- [1..10], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2] 이제 우리가 고려하지 않은 조건은 둘레가 24라는 조건 하나뿐입니다. 이 조건 하나까지 반영해서 답을 구해 봅시다. Prelude> [(a,b,c)| c <- [1..10], b <- [1..c], a <- [1..b], a^2 + b^2 == c^2, a+b+c==24] [(6,8,10)]
  • 27. 연습 문제 • swap 페어의 리스트를 받아서 리스트의 모든 원소를 순서를 바꾸는 함수를 만들어봅시다. 예를 들어 swap [(1,2), (3,4), (5,6), (7,8)]은 [(2,1), (4,3), (6,5), (8,7)]을 리턴해야합니다. • sum 리스트를 받아서 리스트의 모든 원소의 합을 구하는 함수를 만들어봅시다. 이미 표준 라이브러리에 존재하는 함수니 sum 외의 다른 이름으로 작성하셔야합니다. 예를 들어 sum’ [1,2,3,4,5] 는 15를 리턴해야합니다. • divisors 숫자 하나를 받아 그 숫자의 모든 약수 리스트를 리턴하는 함수를 만들어봅시다. 예를 들어 divisors 20 은 [1,2,4,5,10,20]을 리턴해야합니다.