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]
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, …로 표시
• 어떤 타입이든 될 수 있음
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
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)
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