SlideShare a Scribd company logo
하스켈 프로그래밍 입
문
하스켈 학교 2016년 5월 14일
서광열
출처: https://wiki.haskell.org/Haskell_logos/New_logo_ideas
출처: http://i.imgur.com/GHxmrsR.jpg
교재
역사
1930s
Alonzo Church
람다 대수
1950s
John McCarthy의
Lisp
1960s
Peter Landin’s ISWIM
첫 번째 순수 함수 언어
1970s
John Backus’s FP
고차함수와 프로그램의 이해를 강
조한 함수 언어
1970s
Robin Milner의 ML
첫 번째 현대적인 함수 언어
타입 추론과 polymorphic 타입 제공
1970s - 1980s
David Turner의 Miranda
lazy 함수 언어
역사
1987년
하스켈
PL 연구자들이 모여서 만든 표준 함수 언어
1990s:
Phil Wadler
타입 클래스와 모나드
2003
하스켈 언어 명세 Haskell Report 출
간
2010
개정 버전 출간
중요 특징
• Purely functional
• Statically typed
• Lazy
출처: https://xkcd.com/1312/
프로그래밍 스타일
int total = 0;
for (int i = 1; i <= 10; i++)
total = total + i;
sum [1..10]
Glasgow Haskell Compiler
• 하스켈 컴파일러(ghc)와 인터프리터(ghci) 제공
• www.haskell.org/platform
GHCi
• REPL (Read-Eval-Print Loop)
• 터미널에서 ghci를 실행
$ ghci
GHCi, version 7.10.3: http://www.haskell.org/ghc/ :? for help
Prelude>
Expression
> 2+3*4
14
> (2+3)*4
20
> negate 3
-3
Standard Prelude
> head [1,2,3,4]
1
> tail [1,2,3,4]
[2,3,4]
> [1,2,3,4] !! 2
3
• 하스켈의 표준 라이브러리
• GHCi를 실행하면 자동으로 로딩
> take 3 [1,2,3,4,5]
[1,2,3]
> drop 3 [1,2,3,4,5]
[4,5]
> length [1,2,3,4,5]
5
> sum [1,2,3,4,5]
15
> product [1,2,3,4,5]
120
> [1,2,3] ++ [4,5]
[1,2,3,4,5]
> reverse [1,2,3,4,5]
[5,4,3,2,1]
유용한 GHCi 명령
명령 의미
:load name 스크립트를 로드
:reload 현재 스크립트를 다시 로드
:type expr expr의 타입을 보여줌
:? 모든 명령을 보여줌
:quit GHCi를 종료
Function Application
• 함수 f와 인자 a
• f a
• 함수 f와 인자 a, b
• f a b
• 함수 f와 인자 a, b, c
• f a b c
• 함수 f, g와 인자 a, b
• f a + g b
하스켈 스크립트
• 함수를 정의할 수 있음
• .hs 확장자를 가짐
-- test.hs
main = putStrLn "Hello World!"
$ ghc test.hs -o test
$./test
"Hello World"
하스켈 함수 정의
-- test.hs
double x = x + x
square x = x * x
$ ghci test.hs
Prelude> double 10
20
Prelude> square 10
100
하스켈 함수 정의
fac n = product [1..n]
average ns = sum ns `div` length ns
Naming
• 요구사항
• 함수와 인자 이름은 소문자
• myFun, fun1, arg_2, x'
• 타입은 대문자
• Bool, Char, String
• 컨벤션
• 리스트 인자는 보통 s를 끝에 붙임
• xs, ns, nss
레이아웃 규칙
좋은 예
a = 10
b = 20
c = 30
나쁜 예
a = 10
b = 20
c = 30
나쁜 예
a = 10
b = 20
c = 30
레이아웃 규칙
a = b + c
where
b = 1
c = 2
d = a * 2
타입
• 연관된 값들의 집합
• 예) Bool 타입은 True 값과 False 값을 가짐
타입 오류
> 1 + False
<interactive>:16:3:
No instance for (Num Bool) arising from a use of '+'
In the expression: 1 + False
In an equation for 'it': it = 1 + False
하스켈의 타입
• expression e를 계산했을 때 타입 t가 나오면 e :: t라
고 표기함
• 모든 well formed expression을 타입을 가지며, 컴파
일 타임에 type inference를 통해 자동으로 계산됨
타입 확인하기
> not False
True
> :type not False
not False :: Bool
하스켈의 기본 타입
타입 값
Bool 논리값
Char 문자
String 문자열
Int [-2^29 .. 2^29-1] 사이의 정수
Integer 임의의 정수
Float 부동소수점
리스트 타입
• 리스트: 같은 타입을 가지는 값의 나열
• [False, True, False] :: [Bool]
• ['a', 'b', 'c', 'd'] :: [Char]
• [['a'], ['b', 'c']] :: [[Char]]
• [t]는 t를 원소로 가지는 리스트 타입
리스트 타입
출처: http://learnyouahaskell.com/starting-out
튜플 타입
• 튜플: 서로 다른 타입을 가지는 값의 나열
• (False, True) :: (Bool, Bool)
• (False, 'a', True) :: (Bool, Char, Bool)
• ('a', (False, ('b')) :: (Char, (Bool, Char))
• (True, ['a', 'b']) :: (Bool, [Char])
• (t1, t2, …, tn)은 j번째 원소가 tj 타입인 n튜플 타입
함수 타입
• 함수: 한 타입의 값을 다른 타입의 값으로 매핑
• not :: Bool -> Bool
• even :: Int -> Bool
• t1 -> t2는 타입 t1의 값을 타입 t2의 값으로 매핑하는
함수의 타입
함수 타입
add :: (Int, Int) -> Int
add (x,y) = x + y
zeroto :: Int -> [Int]
zeroto n = [0..n]
Curried 함수
• curried 함수: 함수를 결과로 리턴하여 인자 하나짜
리 함수로 인자 여러 개의 함수를 표현
add :: (Int, Int) -> Int
add (x, y) = x + y
add' :: Int -> (Int -> Int)
add' x y = x + y
Partial Application
• Curried function에 인자를 일부만 적용해서 새로운
함수를 만들 수 있음
• add' 1 :: Int -> Int
• take 5 :: [Int] -> [Int]
• drop 5 :: [Int] -> [Int]
Currying의 컨벤션
• 괄호가 너무 많아지는 것을 방지하기 위해 ->는
right-associative함
• Int -> Int -> Int -> Int
• Int -> (Int -> (Int -> Int))
Curried 함수의 application
• 반대로 function application은 left associative함
• 따라서 mult x y z는 (((mult x) y) z)를 의미함
• 튜플을 명시적으로 사용하지 않으면 모든 하스켈 함
수는 기본적으로 curried 함수가 됨
타입 변수
> :t head
head :: [a] -> a
> :t fst
fst :: (a, b) -> a
• 타입 변수는 소문자 a, b, c, …로 표시
• 어떤 타입이든 될 수 있음
Polymorphic 함수
• polymorphic 함수: 타입이 하나 이상의 타입 변수를
포함
• length :: [a] -> Int
• 모든 타입 a에 대해서 [a]를 주면 Int를 리턴함
Polymorphic 함수
> length [False,True]
2
> length [1,2,3,4]
4
> length ['a','b','c']
3
> length ["hello","world"]
2
Prelude에 정의된
Polymorphic 함수
• fst :: (a, b) -> a
• head :: [a] -> a
• take :: Int -> [a] -> [a]
• zip :: [a] -> [b] -> [(a, b)]
• id :: a -> a
Overloaded 함수
• overloaded 함수: 타입이 하나 이상의 class
constraint를 가지고 있는 polymorphic한 함수
• (+) :: Num a => a -> a -> a
Overloaded 함수 (+)
> 1 + 2
3
> 1.0 + 2.0
3.0
> 'a' + 'b'
ERROR
Overloaded 함수 (==)
> 5 == 5
True
> 5 /= 5
False
> 'a' == 'a'
True
> "Ho Ho" == "Ho Ho"
True
> 3.432 == 3.432
True
Overloaded 함수 read
> read "5" :: Int
5
> read "5" :: Float
5.0
> (read "[1,2,3,4]" :: [Int])
[1,2,3,4]
> (read "(3, 'a')" :: (Int, Char))
(3, 'a')
하스켈의 타입클래스들
• Num: 숫자 타입
• (+) :: Num a -> a -> a -> a
• Eq: 같은지 비교가 가능한 타입
• (==) :: Eq a => a -> a -> Bool
• Ord: 순서가 비교 가능한 타입
• (<) :: Ord a => a -> a -> Bool
하스켈의 타입클래스들
• Show: 해당 타입을 문자열로 변환
• show :: Show a => a -> String
• Read: 문자열을 해당 타입으로 변환
• read :: Read a => String -> a
Overloaded number literal
• 하스켈의 상수는 여러 타입을 가짐
> : t 123
123 :: Num a => a
> :t (123 :: Int)
(123 :: Int) :: Int
> :t (123 :: Double)
(123 :: Double) :: Double
> :t (123 :: Int)
(123 :: Int) :: Int
조건 expression
abs :: Int -> Int
abs n = if n >= 0 then n else -n
signum :: Int -> Int
signum n = if n <0 then -1 else
if n == 0 then 0 else 1
• 하스켈에서 항상 값을 리턴해야 하기 때문에 else 구
문을 생략할 수 없음
let과 where
let y = a*b
f x = (x+y)/y
in f c + f d
f x y | y>z = ...
| y==z = ...
| y<z = ...
where z = x*x
Guard
abs n | n >= 0 = n
| otherwise = -n
signum n | n < 0 = -1
| n == 0 = 0
| otherwise = 1
패턴 매칭
not :: Bool -> Bool
not False = True
not True = False
(&&) :: Bool -> Bool -> Bool
True && True = True
_ && _ = False
잘못된 패턴 매칭
(&&) :: Bool -> Bool -> Bool
_ && _ = False
True && True = True
리스트 패턴
• 리스트 [1,2,3,4]는 1:(2:(3:(4:[])))
• (:)는 cons 연산자라고 불림
head :: [a] -> a
head (x:_) = x
tail :: [a] -> [a]
tail (_:xs) = xs
Lambda expression
• lambda expression을 이용하면 이름 없는 함수를 생
성할 수 있음
• x -> x + x
• 인자 x를 받아서 x + x를 리턴하는 함수
Lambda expression
add x y = x + y
add = x -> (y -> x + y)
const :: a -> b -> a
const x _ = x
const :: a -> (b -> a)
const x = _ -> x
Lambda expression
odds n = map f [0..n-1]
where
f x = x * 2 + 1
odd n = map (x -> x * 2 + 1) [0..n-1]
Section
• 1 + 2는 (+) 1 2로 쓸 수 있음
• 인자 중에 하나만 제공해서 새로운 함수를 만들 수도
있음
> (1+) 2
3
> (+2) 1
Section 예제
• (1+)
• (1/)
• (*2)
• (/2)
재귀 함수
• 하스켈에서 함수는 자기 자신으로 정의 가능한데 이
런 함수를 재귀 함수라고 부름
fac 0 = 1
fac n = n * fac (n-1)
fac 함수의 실행
fac 3
= 3 * fac 2
= 3 * (2 * fac 1)
= 3 * (2 * (1 * fac 0))
= 3 * (2 * (1 * 1))
= 3* (2 * 1)
= 3 * 2
= 6
재귀 함수의 장점
• 일부 함수는 재귀로 정의하는 것이 더 쉬움
• 재귀로 정의한 함수는 mathematical induction을 이
용해 property를 증명할 수 있음
리스트에 대한 재귀
product :: Num a => [a] -> a
product [] = 1
product (n:ns) = n * product ns
length :: [a] -> int
length [] = 0
length (_:xs) = 1 + length xs
product 함수의 실행
product [2,3,4]
= 2 * product [3,4]
= 2 * (3 * product [4])
= 2 * (3 * (4 * product []))
= 2 * (3 * (4 * 1))
= 24
length 함수의 실행
length [1,2,3]
= 1 + length [2,3]
= 1 + (1 + length [3])
= 1 + (1 + (1 + length []))
= 1 + (1 + (1 + 0))
= 3
리스트에 대한 재귀
reverse :: [a] -> [a]
reverse [] = []
reverse (x:xs) = reverse xs ++ [x]
reverse 함수의 실행
reverse [1,2,3]
= reverse [2,3] ++ [1]
= (reverse [3] ++ [2]) ++ [1]
= ((reverse [] ++ [3]) ++ [2]) ++ [1]
= (([] ++ [3]) ++ [2]) ++ [1]
= [3,2,1]
인자가 여러 개인 재귀 함
수
zip :: [a] -> [b] -> [(a,b)]
zip [] _ = []
zip _ [] = []
zip (x:xs) (y:ys) = (x, y) : zip xs ys
리스트에 대한 재귀
drop :: Int -> [a] -> [a]
drop 0 xs = xs
drop _ [] = []
drop n (_:xs) = drop (n-1) xs
(++) :: [a] -> [a] -> [a]
[] ++ ys = ys
(x:xs) ++ ys = x:(xs ++ ys)
append 시각화
xs = [0, 1, 2]
ys = [3,4,5]
zs = xs ++ ys
퀵소트
qsort :: Ord a => [a] -> [a]
qsort (x:xs) =
qsort smaller ++ [x] ++ qsort larger
where
smaller = [a | a <- xs, a <= x]
larger = [b | b <- xs, b > x]
퀵소트
q [3,2,4,1,5]
++ [3] ++q [2,1] q [4,5]
++ [2] ++q [1] q [] q [] ++ [4] ++ q [5]
[1] [5]
고차함수
• 고차함수: 함수를 인자로 받거나 함수를 결과로 리턴
하는 함수
twice :: (a -> a) -> a -> a
twice f x = f (f x)
map 함수
• map :: (a -> b) -> [a] -> [b]
> map (+1) [1,3,5,7]
[2,4,6,8]
map 함수의 정의
-- list comprehension
map f xs = [f x | x <- xs]
-- recursive definition
map f [] = []
map f (x:xs) = f x : map f xs
filter 함수
• filter :: (a -> Bool) -> [a] -> [b]
> filter even [1..10]
[2,4,6,8,10]
filter 함수의 정의
-- list comprehension
filter p xs = [x | x <- xs, p x]
-- recursive definition
filter p [] = []
filter p (x:xs)
| p x = x : filter p xs
| otherwise = filter p xs
foldr 함수
• foldr는 리스트에 대한 재귀의 패턴을 표현함
• f [] = v
• f (x:xs) = x ⊕ f xs
직접 재귀 예제
-- v = 0, ⊕ = +
sum [] = 0
sum (x:xs) = x + sum xs
-- v = 0, ⊕ = *
product [] = 1
product (x:xs) = x * product xs
-- v = 0, ⊕ = &&
and [] = True
and (x:xs) = x && and xs
foldr을 이용한 재귀 예제
sum = foldr (+) 0
product = foldr (*) 1
or = foldr (||) false
and = foldr (&&) True
foldr의 정의
foldr :: (a -> b -> b) -> b -> [a] ->b
foldr f v [] = v
foldr f v (x:xs) = f x (foldr f v xs)
foldr 시각화
sum의 계산
sum [1,2,3]
= foldr (+) 0 [1,2,3]
= foldr (+) 0 (1:(2:(3:[])))
= 1+(2+(3+0))
= 6
product의 계산
product [1,2,3]
= foldr (*) 1 [1,2,3]
= foldr (*) 1 (1:(2:(3:[])))
= 1*(2*(3*1))
= 6
foldr를 이용한 length 함수
length = foldr (_ n -> 1 + n) 0
length [1,2,3]
= length (1:(2:(3:[])))
= foldr (_ n -> 1 + n) 0
foldr를 이용한 재귀 함수
reverse = foldr (x xs -> xs ++ [x]) []
(++ ys) = foldr (:) ys
foldr이 유용한 이유
• 직접적인 재귀보다 정의하기 쉬움
• 함수의 property를 foldr의 algebraic property를 이용
하여 증명할 수 있음
• 프로그램 최적화가 쉬워짐
고차 함수의 예
takeWhile
takeWhile :: (a -> Bool) -> [a] -> [a]
takeWhile p [] = []
takeWhile p (x:xs)
| p x = x : takeWhile p xs
| otherwise = []
> takeWhile (/= ' ') "abc def"
"abc"
참고 자료
1. Slides of Programming in Haskell
• http://www.cs.nott.ac.uk/~pszgmh/book.html
2. Learn You a Haskell for Great Good!
• http://learnyouahaskell.com/chapters
3. A Gentle Introduction to Haskell 98
• https://www.haskell.org/tutorial/haskell-98-
tutorial.pdf
연습 문제
1. 리스트의 마지막 원소를 리턴하는 함수 myLast를
작성하시오
• myLast :: [a] -> a
2. 리스트의 k번째 원소를 리턴하는 함수 elementAt
를 작성하시오
• elementAt :: [a] -> Int -> a
연습 문제
• 리스트가 palindrome인지 아닌지를 리턴하는 함수를 작성하
시오
• isPalindrome :: (Eq a) => [a] -> Bool
> isPalindrome [1,2,3]
False
> isPalindrome "madamimadam"
True
> isPalindrome [1,2,4,8,16,8,4,2,1]
True
연습 문제
• 연속된 리스트 원소를 제거하는 compress 함수를
작성하시오
• compress :: Eq a => [a] -> [a]
> compress "aaaabccaadeeee"
"abcade"
연습 문제
• 리스트를 run-length 인코딩으로 리턴하는 함수
encode를 작성하시오
• encode :: Eq a => [a] -> [(Int, a)]
> encode "aaaabccaadeeee"
[(4,'a'),(1,'b'),(2,'c'),(2,'a'),(1,'d'),(4,'e')]
숙제
• CIS 194 Homework 1,2,3,4,5번을 풉니다
• http://www.seas.upenn.edu/~cis194/lectures.html

More Related Content

PPTX
종이접기(fold) 프로그래밍
PPTX
하스켈 프로그래밍 입문 2
PDF
하스켈 모나드
PPTX
Valentine
PPTX
R 프로그래밍 기본 문법
PDF
Haskell study 5
PDF
Haskell study 10
PDF
알고리즘과 자료구조
종이접기(fold) 프로그래밍
하스켈 프로그래밍 입문 2
하스켈 모나드
Valentine
R 프로그래밍 기본 문법
Haskell study 5
Haskell study 10
알고리즘과 자료구조

What's hot (20)

PDF
Tensorflow regression 텐서플로우 회귀
PPTX
R 기본-데이타형 소개
PPTX
Python 스터디
PPTX
R 프로그래밍-향상된 데이타 조작
PDF
R 스터디 네번째
PDF
4. stack
PDF
Python Programming: Function
PDF
Example
PDF
5. queue
PDF
ALS WS에 대한 이해 자료
PDF
Haskell study 4
PPTX
R 프로그램의 이해와 활용 v1.1
PDF
3. linked list
PPTX
하스켈로 알고리즘 문제 풀기 2
PPTX
하스켈로 알고리즘 문제 풀기
PPTX
하스켈 성능 튜닝 2
PPTX
파이썬 Numpy 선형대수 이해하기
PDF
Data Structure - 1st Study
PPTX
하스켈 성능 튜닝
PDF
Haskell study 2
Tensorflow regression 텐서플로우 회귀
R 기본-데이타형 소개
Python 스터디
R 프로그래밍-향상된 데이타 조작
R 스터디 네번째
4. stack
Python Programming: Function
Example
5. queue
ALS WS에 대한 이해 자료
Haskell study 4
R 프로그램의 이해와 활용 v1.1
3. linked list
하스켈로 알고리즘 문제 풀기 2
하스켈로 알고리즘 문제 풀기
하스켈 성능 튜닝 2
파이썬 Numpy 선형대수 이해하기
Data Structure - 1st Study
하스켈 성능 튜닝
Haskell study 2
Ad

Viewers also liked (12)

PPTX
하스켈 프로그래밍 입문 4
PDF
Haskell and List
PDF
Haskell Tour (Part 1)
PDF
Lucrazon Global en Español - Presentacion Lucrazon Global - Equipo Pionero Hi...
PPTX
10 dicas para se tornar um ótimo estagiário
PPTX
Campamento maiores 65 anos
PDF
FIN DE CURSO
PDF
Haskell study 1
PDF
Haskell study 0
PDF
Karatbars NUEVA Presentación 2014 - Karatbars en Español - Plan de Compensaci...
PDF
하드웨어 스타트업의 소프트웨어 이야기
PDF
The monad fear
하스켈 프로그래밍 입문 4
Haskell and List
Haskell Tour (Part 1)
Lucrazon Global en Español - Presentacion Lucrazon Global - Equipo Pionero Hi...
10 dicas para se tornar um ótimo estagiário
Campamento maiores 65 anos
FIN DE CURSO
Haskell study 1
Haskell study 0
Karatbars NUEVA Presentación 2014 - Karatbars en Español - Plan de Compensaci...
하드웨어 스타트업의 소프트웨어 이야기
The monad fear
Ad

Similar to 하스켈 프로그래밍 입문 (20)

PPTX
Python programming for Bioinformatics
PPTX
파이썬+Operator+이해하기 20160409
PPTX
파이썬 스터디 2주차
PPTX
Python datatype
PDF
고등학생 R&E Python summary for test
PPT
3ds maxscript 튜토리얼_20151206_서진택
PDF
Javascript개발자의 눈으로 python 들여다보기
PDF
R 스터디 첫번째
PPTX
R intro
PDF
자료구조02
PDF
RPG Maker와 Ruby로 코딩 시작하기 Day 3
PDF
Python Programming: Type and Object
PDF
Haskell study 13
PDF
Python machine learning Ch.4
PDF
12 1. multi-dimensional array
PDF
[C++ Korea 2nd Seminar] C++17 Key Features Summary
PDF
파이썬 기본 문법
PDF
함수형 프로그래밍? 그래서 어떻게
PPTX
파이썬+함수이해하기 20160229
PDF
Python
Python programming for Bioinformatics
파이썬+Operator+이해하기 20160409
파이썬 스터디 2주차
Python datatype
고등학생 R&E Python summary for test
3ds maxscript 튜토리얼_20151206_서진택
Javascript개발자의 눈으로 python 들여다보기
R 스터디 첫번째
R intro
자료구조02
RPG Maker와 Ruby로 코딩 시작하기 Day 3
Python Programming: Type and Object
Haskell study 13
Python machine learning Ch.4
12 1. multi-dimensional array
[C++ Korea 2nd Seminar] C++17 Key Features Summary
파이썬 기본 문법
함수형 프로그래밍? 그래서 어떻게
파이썬+함수이해하기 20160229
Python

하스켈 프로그래밍 입문

  • 1. 하스켈 프로그래밍 입 문 하스켈 학교 2016년 5월 14일 서광열
  • 5. 역사 1930s Alonzo Church 람다 대수 1950s John McCarthy의 Lisp 1960s Peter Landin’s ISWIM 첫 번째 순수 함수 언어 1970s John Backus’s FP 고차함수와 프로그램의 이해를 강 조한 함수 언어 1970s Robin Milner의 ML 첫 번째 현대적인 함수 언어 타입 추론과 polymorphic 타입 제공 1970s - 1980s David Turner의 Miranda lazy 함수 언어
  • 6. 역사 1987년 하스켈 PL 연구자들이 모여서 만든 표준 함수 언어 1990s: Phil Wadler 타입 클래스와 모나드 2003 하스켈 언어 명세 Haskell Report 출 간 2010 개정 버전 출간
  • 7. 중요 특징 • Purely functional • Statically typed • Lazy 출처: https://xkcd.com/1312/
  • 8. 프로그래밍 스타일 int total = 0; for (int i = 1; i <= 10; i++) total = total + i; sum [1..10]
  • 9. Glasgow Haskell Compiler • 하스켈 컴파일러(ghc)와 인터프리터(ghci) 제공 • www.haskell.org/platform
  • 10. GHCi • REPL (Read-Eval-Print Loop) • 터미널에서 ghci를 실행 $ ghci GHCi, version 7.10.3: http://www.haskell.org/ghc/ :? for help Prelude>
  • 12. Standard Prelude > head [1,2,3,4] 1 > tail [1,2,3,4] [2,3,4] > [1,2,3,4] !! 2 3 • 하스켈의 표준 라이브러리 • GHCi를 실행하면 자동으로 로딩
  • 13. > take 3 [1,2,3,4,5] [1,2,3] > drop 3 [1,2,3,4,5] [4,5] > length [1,2,3,4,5] 5
  • 14. > sum [1,2,3,4,5] 15 > product [1,2,3,4,5] 120 > [1,2,3] ++ [4,5] [1,2,3,4,5] > reverse [1,2,3,4,5] [5,4,3,2,1]
  • 15. 유용한 GHCi 명령 명령 의미 :load name 스크립트를 로드 :reload 현재 스크립트를 다시 로드 :type expr expr의 타입을 보여줌 :? 모든 명령을 보여줌 :quit GHCi를 종료
  • 16. Function Application • 함수 f와 인자 a • f a • 함수 f와 인자 a, b • f a b • 함수 f와 인자 a, b, c • f a b c • 함수 f, g와 인자 a, b • f a + g b
  • 17. 하스켈 스크립트 • 함수를 정의할 수 있음 • .hs 확장자를 가짐 -- test.hs main = putStrLn "Hello World!" $ ghc test.hs -o test $./test "Hello World"
  • 18. 하스켈 함수 정의 -- test.hs double x = x + x square x = x * x $ ghci test.hs Prelude> double 10 20 Prelude> square 10 100
  • 19. 하스켈 함수 정의 fac n = product [1..n] average ns = sum ns `div` length ns
  • 20. Naming • 요구사항 • 함수와 인자 이름은 소문자 • myFun, fun1, arg_2, x' • 타입은 대문자 • Bool, Char, String • 컨벤션 • 리스트 인자는 보통 s를 끝에 붙임 • xs, ns, nss
  • 21. 레이아웃 규칙 좋은 예 a = 10 b = 20 c = 30 나쁜 예 a = 10 b = 20 c = 30 나쁜 예 a = 10 b = 20 c = 30
  • 22. 레이아웃 규칙 a = b + c where b = 1 c = 2 d = a * 2
  • 23. 타입 • 연관된 값들의 집합 • 예) Bool 타입은 True 값과 False 값을 가짐
  • 24. 타입 오류 > 1 + False <interactive>:16:3: No instance for (Num Bool) arising from a use of '+' In the expression: 1 + False In an equation for 'it': it = 1 + False
  • 25. 하스켈의 타입 • expression e를 계산했을 때 타입 t가 나오면 e :: t라 고 표기함 • 모든 well formed expression을 타입을 가지며, 컴파 일 타임에 type inference를 통해 자동으로 계산됨
  • 26. 타입 확인하기 > not False True > :type not False not False :: Bool
  • 27. 하스켈의 기본 타입 타입 값 Bool 논리값 Char 문자 String 문자열 Int [-2^29 .. 2^29-1] 사이의 정수 Integer 임의의 정수 Float 부동소수점
  • 28. 리스트 타입 • 리스트: 같은 타입을 가지는 값의 나열 • [False, True, False] :: [Bool] • ['a', 'b', 'c', 'd'] :: [Char] • [['a'], ['b', 'c']] :: [[Char]] • [t]는 t를 원소로 가지는 리스트 타입
  • 30. 튜플 타입 • 튜플: 서로 다른 타입을 가지는 값의 나열 • (False, True) :: (Bool, Bool) • (False, 'a', True) :: (Bool, Char, Bool) • ('a', (False, ('b')) :: (Char, (Bool, Char)) • (True, ['a', 'b']) :: (Bool, [Char]) • (t1, t2, …, tn)은 j번째 원소가 tj 타입인 n튜플 타입
  • 31. 함수 타입 • 함수: 한 타입의 값을 다른 타입의 값으로 매핑 • not :: Bool -> Bool • even :: Int -> Bool • t1 -> t2는 타입 t1의 값을 타입 t2의 값으로 매핑하는 함수의 타입
  • 32. 함수 타입 add :: (Int, Int) -> Int add (x,y) = x + y zeroto :: Int -> [Int] zeroto n = [0..n]
  • 33. Curried 함수 • curried 함수: 함수를 결과로 리턴하여 인자 하나짜 리 함수로 인자 여러 개의 함수를 표현 add :: (Int, Int) -> Int add (x, y) = x + y add' :: Int -> (Int -> Int) add' x y = x + y
  • 34. Partial Application • Curried function에 인자를 일부만 적용해서 새로운 함수를 만들 수 있음 • add' 1 :: Int -> Int • take 5 :: [Int] -> [Int] • drop 5 :: [Int] -> [Int]
  • 35. Currying의 컨벤션 • 괄호가 너무 많아지는 것을 방지하기 위해 ->는 right-associative함 • Int -> Int -> Int -> Int • Int -> (Int -> (Int -> Int))
  • 36. Curried 함수의 application • 반대로 function application은 left associative함 • 따라서 mult x y z는 (((mult x) y) z)를 의미함 • 튜플을 명시적으로 사용하지 않으면 모든 하스켈 함 수는 기본적으로 curried 함수가 됨
  • 37. 타입 변수 > :t head head :: [a] -> a > :t fst fst :: (a, b) -> a • 타입 변수는 소문자 a, b, c, …로 표시 • 어떤 타입이든 될 수 있음
  • 38. Polymorphic 함수 • polymorphic 함수: 타입이 하나 이상의 타입 변수를 포함 • length :: [a] -> Int • 모든 타입 a에 대해서 [a]를 주면 Int를 리턴함
  • 39. Polymorphic 함수 > length [False,True] 2 > length [1,2,3,4] 4 > length ['a','b','c'] 3 > length ["hello","world"] 2
  • 40. Prelude에 정의된 Polymorphic 함수 • fst :: (a, b) -> a • head :: [a] -> a • take :: Int -> [a] -> [a] • zip :: [a] -> [b] -> [(a, b)] • id :: a -> a
  • 41. Overloaded 함수 • overloaded 함수: 타입이 하나 이상의 class constraint를 가지고 있는 polymorphic한 함수 • (+) :: Num a => a -> a -> a
  • 42. Overloaded 함수 (+) > 1 + 2 3 > 1.0 + 2.0 3.0 > 'a' + 'b' ERROR
  • 43. Overloaded 함수 (==) > 5 == 5 True > 5 /= 5 False > 'a' == 'a' True > "Ho Ho" == "Ho Ho" True > 3.432 == 3.432 True
  • 44. Overloaded 함수 read > read "5" :: Int 5 > read "5" :: Float 5.0 > (read "[1,2,3,4]" :: [Int]) [1,2,3,4] > (read "(3, 'a')" :: (Int, Char)) (3, 'a')
  • 45. 하스켈의 타입클래스들 • Num: 숫자 타입 • (+) :: Num a -> a -> a -> a • Eq: 같은지 비교가 가능한 타입 • (==) :: Eq a => a -> a -> Bool • Ord: 순서가 비교 가능한 타입 • (<) :: Ord a => a -> a -> Bool
  • 46. 하스켈의 타입클래스들 • Show: 해당 타입을 문자열로 변환 • show :: Show a => a -> String • Read: 문자열을 해당 타입으로 변환 • read :: Read a => String -> a
  • 47. Overloaded number literal • 하스켈의 상수는 여러 타입을 가짐 > : t 123 123 :: Num a => a > :t (123 :: Int) (123 :: Int) :: Int > :t (123 :: Double) (123 :: Double) :: Double > :t (123 :: Int) (123 :: Int) :: Int
  • 48. 조건 expression abs :: Int -> Int abs n = if n >= 0 then n else -n signum :: Int -> Int signum n = if n <0 then -1 else if n == 0 then 0 else 1 • 하스켈에서 항상 값을 리턴해야 하기 때문에 else 구 문을 생략할 수 없음
  • 49. let과 where let y = a*b f x = (x+y)/y in f c + f d f x y | y>z = ... | y==z = ... | y<z = ... where z = x*x
  • 50. Guard abs n | n >= 0 = n | otherwise = -n signum n | n < 0 = -1 | n == 0 = 0 | otherwise = 1
  • 51. 패턴 매칭 not :: Bool -> Bool not False = True not True = False (&&) :: Bool -> Bool -> Bool True && True = True _ && _ = False
  • 52. 잘못된 패턴 매칭 (&&) :: Bool -> Bool -> Bool _ && _ = False True && True = True
  • 53. 리스트 패턴 • 리스트 [1,2,3,4]는 1:(2:(3:(4:[]))) • (:)는 cons 연산자라고 불림 head :: [a] -> a head (x:_) = x tail :: [a] -> [a] tail (_:xs) = xs
  • 54. Lambda expression • lambda expression을 이용하면 이름 없는 함수를 생 성할 수 있음 • x -> x + x • 인자 x를 받아서 x + x를 리턴하는 함수
  • 55. Lambda expression add x y = x + y add = x -> (y -> x + y) const :: a -> b -> a const x _ = x const :: a -> (b -> a) const x = _ -> x
  • 56. Lambda expression odds n = map f [0..n-1] where f x = x * 2 + 1 odd n = map (x -> x * 2 + 1) [0..n-1]
  • 57. Section • 1 + 2는 (+) 1 2로 쓸 수 있음 • 인자 중에 하나만 제공해서 새로운 함수를 만들 수도 있음 > (1+) 2 3 > (+2) 1
  • 58. Section 예제 • (1+) • (1/) • (*2) • (/2)
  • 59. 재귀 함수 • 하스켈에서 함수는 자기 자신으로 정의 가능한데 이 런 함수를 재귀 함수라고 부름 fac 0 = 1 fac n = n * fac (n-1)
  • 60. fac 함수의 실행 fac 3 = 3 * fac 2 = 3 * (2 * fac 1) = 3 * (2 * (1 * fac 0)) = 3 * (2 * (1 * 1)) = 3* (2 * 1) = 3 * 2 = 6
  • 61. 재귀 함수의 장점 • 일부 함수는 재귀로 정의하는 것이 더 쉬움 • 재귀로 정의한 함수는 mathematical induction을 이 용해 property를 증명할 수 있음
  • 62. 리스트에 대한 재귀 product :: Num a => [a] -> a product [] = 1 product (n:ns) = n * product ns length :: [a] -> int length [] = 0 length (_:xs) = 1 + length xs
  • 63. product 함수의 실행 product [2,3,4] = 2 * product [3,4] = 2 * (3 * product [4]) = 2 * (3 * (4 * product [])) = 2 * (3 * (4 * 1)) = 24
  • 64. length 함수의 실행 length [1,2,3] = 1 + length [2,3] = 1 + (1 + length [3]) = 1 + (1 + (1 + length [])) = 1 + (1 + (1 + 0)) = 3
  • 65. 리스트에 대한 재귀 reverse :: [a] -> [a] reverse [] = [] reverse (x:xs) = reverse xs ++ [x]
  • 66. reverse 함수의 실행 reverse [1,2,3] = reverse [2,3] ++ [1] = (reverse [3] ++ [2]) ++ [1] = ((reverse [] ++ [3]) ++ [2]) ++ [1] = (([] ++ [3]) ++ [2]) ++ [1] = [3,2,1]
  • 67. 인자가 여러 개인 재귀 함 수 zip :: [a] -> [b] -> [(a,b)] zip [] _ = [] zip _ [] = [] zip (x:xs) (y:ys) = (x, y) : zip xs ys
  • 68. 리스트에 대한 재귀 drop :: Int -> [a] -> [a] drop 0 xs = xs drop _ [] = [] drop n (_:xs) = drop (n-1) xs (++) :: [a] -> [a] -> [a] [] ++ ys = ys (x:xs) ++ ys = x:(xs ++ ys)
  • 69. append 시각화 xs = [0, 1, 2] ys = [3,4,5] zs = xs ++ ys
  • 70. 퀵소트 qsort :: Ord a => [a] -> [a] qsort (x:xs) = qsort smaller ++ [x] ++ qsort larger where smaller = [a | a <- xs, a <= x] larger = [b | b <- xs, b > x]
  • 71. 퀵소트 q [3,2,4,1,5] ++ [3] ++q [2,1] q [4,5] ++ [2] ++q [1] q [] q [] ++ [4] ++ q [5] [1] [5]
  • 72. 고차함수 • 고차함수: 함수를 인자로 받거나 함수를 결과로 리턴 하는 함수 twice :: (a -> a) -> a -> a twice f x = f (f x)
  • 73. map 함수 • map :: (a -> b) -> [a] -> [b] > map (+1) [1,3,5,7] [2,4,6,8]
  • 74. map 함수의 정의 -- list comprehension map f xs = [f x | x <- xs] -- recursive definition map f [] = [] map f (x:xs) = f x : map f xs
  • 75. filter 함수 • filter :: (a -> Bool) -> [a] -> [b] > filter even [1..10] [2,4,6,8,10]
  • 76. filter 함수의 정의 -- list comprehension filter p xs = [x | x <- xs, p x] -- recursive definition filter p [] = [] filter p (x:xs) | p x = x : filter p xs | otherwise = filter p xs
  • 77. foldr 함수 • foldr는 리스트에 대한 재귀의 패턴을 표현함 • f [] = v • f (x:xs) = x ⊕ f xs
  • 78. 직접 재귀 예제 -- v = 0, ⊕ = + sum [] = 0 sum (x:xs) = x + sum xs -- v = 0, ⊕ = * product [] = 1 product (x:xs) = x * product xs -- v = 0, ⊕ = && and [] = True and (x:xs) = x && and xs
  • 79. foldr을 이용한 재귀 예제 sum = foldr (+) 0 product = foldr (*) 1 or = foldr (||) false and = foldr (&&) True
  • 80. foldr의 정의 foldr :: (a -> b -> b) -> b -> [a] ->b foldr f v [] = v foldr f v (x:xs) = f x (foldr f v xs)
  • 82. sum의 계산 sum [1,2,3] = foldr (+) 0 [1,2,3] = foldr (+) 0 (1:(2:(3:[]))) = 1+(2+(3+0)) = 6
  • 83. product의 계산 product [1,2,3] = foldr (*) 1 [1,2,3] = foldr (*) 1 (1:(2:(3:[]))) = 1*(2*(3*1)) = 6
  • 84. foldr를 이용한 length 함수 length = foldr (_ n -> 1 + n) 0 length [1,2,3] = length (1:(2:(3:[]))) = foldr (_ n -> 1 + n) 0
  • 85. foldr를 이용한 재귀 함수 reverse = foldr (x xs -> xs ++ [x]) [] (++ ys) = foldr (:) ys
  • 86. foldr이 유용한 이유 • 직접적인 재귀보다 정의하기 쉬움 • 함수의 property를 foldr의 algebraic property를 이용 하여 증명할 수 있음 • 프로그램 최적화가 쉬워짐
  • 87. 고차 함수의 예 takeWhile takeWhile :: (a -> Bool) -> [a] -> [a] takeWhile p [] = [] takeWhile p (x:xs) | p x = x : takeWhile p xs | otherwise = [] > takeWhile (/= ' ') "abc def" "abc"
  • 88. 참고 자료 1. Slides of Programming in Haskell • http://www.cs.nott.ac.uk/~pszgmh/book.html 2. Learn You a Haskell for Great Good! • http://learnyouahaskell.com/chapters 3. A Gentle Introduction to Haskell 98 • https://www.haskell.org/tutorial/haskell-98- tutorial.pdf
  • 89. 연습 문제 1. 리스트의 마지막 원소를 리턴하는 함수 myLast를 작성하시오 • myLast :: [a] -> a 2. 리스트의 k번째 원소를 리턴하는 함수 elementAt 를 작성하시오 • elementAt :: [a] -> Int -> a
  • 90. 연습 문제 • 리스트가 palindrome인지 아닌지를 리턴하는 함수를 작성하 시오 • isPalindrome :: (Eq a) => [a] -> Bool > isPalindrome [1,2,3] False > isPalindrome "madamimadam" True > isPalindrome [1,2,4,8,16,8,4,2,1] True
  • 91. 연습 문제 • 연속된 리스트 원소를 제거하는 compress 함수를 작성하시오 • compress :: Eq a => [a] -> [a] > compress "aaaabccaadeeee" "abcade"
  • 92. 연습 문제 • 리스트를 run-length 인코딩으로 리턴하는 함수 encode를 작성하시오 • encode :: Eq a => [a] -> [(Int, a)] > encode "aaaabccaadeeee" [(4,'a'),(1,'b'),(2,'c'),(2,'a'),(1,'d'),(4,'e')]
  • 93. 숙제 • CIS 194 Homework 1,2,3,4,5번을 풉니다 • http://www.seas.upenn.edu/~cis194/lectures.html