하스켈 프로그래밍 입문 2

90
하하하 하하하하하 하하 2 하하하 하하 2016 하 5 하 21 하 하하하

Upload: kwang-yul-seo

Post on 17-Jan-2017

573 views

Category:

Engineering


0 download

TRANSCRIPT

Page 1: 하스켈 프로그래밍 입문 2

하스켈 프로그래밍입문 2하스켈 학교 2016 년 5 월 21 일서광열

Page 2: 하스켈 프로그래밍 입문 2

함수 합성(.): 두 함수를 인자로 받아 두 함수의 합성 함수를 리턴함(.) :: (b -> c) -> (a -> b) -> (a -> c)

f . g = \x -> f (g x)

odd :: Int -> Bool

odd = not . even

Page 3: 하스켈 프로그래밍 입문 2

$ 를 이용한 함수 application

($) :: (a -> b) -> a -> b

f $ x = f x

> map ($ 3) [(4+), (10*), (^2), sqrt]

[7.0,30.0,9.0,1.7320508075688772]

($): 함수 f 와 인자 a 를 받아 f a 를 호출함

Page 4: 하스켈 프로그래밍 입문 2

Type synonym• type String = [Char]

• type Pos = (Int, Int)origin :: Pos

origin = (0, 0)

left :: Pos -> Pos

left (x, y) = (x-1, y)

Page 5: 하스켈 프로그래밍 입문 2

Type synonym

• type Pair a = (a, a)

mult :: Pair Int -> Int

mult (m, n) = m *n

copy :: a -> Pair a

copy x = (x, x)

Page 6: 하스켈 프로그래밍 입문 2

Type synonym• Can be nested

• type Trans = Pos -> Pos

• Can't be recursive

• type Tree = (Int, [Tree])

Page 7: 하스켈 프로그래밍 입문 2

Algebraic Data Type

Page 8: 하스켈 프로그래밍 입문 2

Algebraic Data Typedata Answer = Yes | No | Unknown

answers :: [Answer]

answers = [Yes, No, Unknown]

flip :: Answer -> Answer

flip Yes = No

flip No = Yes

flip Unknown = Unknown

Page 9: 하스켈 프로그래밍 입문 2

Algebraic Data Typedata Shape = Circle Float

| Rect Float Float

square :: Float -> Shape

square n = Rect n n

area :: Shape -> Float

area (Circle r) = pi * r^2

area (Rect x y) = x * y

Circle :: Float -> Shape

Rect :: Float -> Float -> Shape

Page 10: 하스켈 프로그래밍 입문 2

재귀 타입 (Succ)data Nat = Zero | Succ Nat

Zero -- 0

Succ Zero -- 1

Succ (Succ Zero) -- 2

Succ (Succ (Succ Zero)) -- 3

Page 11: 하스켈 프로그래밍 입문 2

재귀 타입 (Succ)nat2int :: Nat -> Int

nat2int Zero = 0

nat2int (Succ n) = 1 + nat2int n

int2nat :: Int -> Nat

int2nat 0 = Zero

int2nat n = Succ (int2nat (n-1))

Page 12: 하스켈 프로그래밍 입문 2

재귀 타입 (Succ)-- converting to and from integers

add :: Nat -> Nat -> Nat

add m n = int2nat (nat2int m + nat2int n)

-- using recursion

add Zero n = n

add (Succ m) n = Succ (add m n)

Page 13: 하스켈 프로그래밍 입문 2

재귀 타입 (Succ)

add (Succ (Succ Zero)) (Succ Zero)

= Succ (add (Succ Zero) (Succ Zero)

= Succ (Succ (add Zero (Succ Zero))

= Succ (Succ (Succ Zero))

Page 14: 하스켈 프로그래밍 입문 2

재귀 타입 (Expr)data Expr = Val Int

| Add Expr Expr

| Mul Expr Expr

-- 1 + (2 * 3)

Add (Val 1) (Mul (Val 2) (Val 3))

Page 15: 하스켈 프로그래밍 입문 2

재귀 타입 (Expr)size :: Expr -> Int

size (Val n) = 1

size (Add x y) = size x + size y

size (Mul x y) = size x + size y

eval :: Expr -> Int

eval (Var n) = n

eval (Add x y) = eval x + eval y

eval (Mul x y) = eval x * eval y

Page 16: 하스켈 프로그래밍 입문 2

재귀 타입 (Binary Tree)data Tree a = Leaf a

| Node (Tree a) a (Tree a)

t: Tree Int

t = Node (Node (Leaf 1) 3 (Leaf 4)) 5

(Node (Leaf 6) 7 (Leaf 9))

Page 17: 하스켈 프로그래밍 입문 2

재귀 타입 (Binary Tree)occurs :: Eq a => a -> Tree a -> Bool

occurs x (Leaf y) = x == y

occurs x (Node l y r) = x == y

|| occurs x l

|| occurs x r

Page 18: 하스켈 프로그래밍 입문 2

재귀 타입 (Binary Tree)flatten :: Tree a -> [a]

flatten (Leaf x) = [x]

flatten (Node l x r) = flatten l

++ [x]

++ flatten r

Page 19: 하스켈 프로그래밍 입문 2

Algebraic Data Type 요약종류 예제

Enumeration data Season = Summer | Winter | Autumn | Spring

Product data Pair = Pair Int Int

Sum data Shape = Circle Float | Rect Float Float

Polymorphic & Recursive

data Tree a = Leaf a | Node (Tree a) a (Tree a)

Page 20: 하스켈 프로그래밍 입문 2

Record

data Person = Person { firstName :: String

, lastName :: String

, age :: Int

}

• 각 필드에 이름을 부여• 필드 이름은 해당 필드 값을 꺼내는 getter 함수가 됨

Page 21: 하스켈 프로그래밍 입문 2

Record 생성 및 getter> :t Person

Person :: String -> String -> Int -> Person

> :t firstName

firstName :: Person -> String

> :t lastName

lastName :: Person -> String

> :t age

age :: Person -> Int

Page 22: 하스켈 프로그래밍 입문 2

Record> let p = Person { firstName = "Kwang", lastName = "Seo", age = 20 }

> firstName p

"Kwang"

> age p

20

Page 23: 하스켈 프로그래밍 입문 2

Record 패턴 매칭fullName :: Person -> String

fullName (Person {firstName = fn, lastName = ln}) =

fn ++ " " ++ ln

Page 24: 하스켈 프로그래밍 입문 2

deriving• Show, Eq 등의 타입 클래스 인스턴스를 자동으로 생성

data Expr = Const Int

| Add Expr Expr

deriving (Eq, Show)

Page 25: 하스켈 프로그래밍 입문 2

타입 클래스class Eq a where

(==) :: a -> a -> Bool

Page 26: 하스켈 프로그래밍 입문 2

타입 클래스data Expr = Const Int

| Add Expr Expr

instance Eq Expr where

(Const _) == (Add _) = False

(Add _) == (Const _) = False

(Const i) == (Const i') = i == i'

(Add x y) == (Add x' y') == x == x' && y == y'

Page 27: 하스켈 프로그래밍 입문 2

타입 클래스class Eq a where

(==), (/=) :: a -> a -> Bool

x/=y = not (x==y)

x==y = not (x/=y)

(==) 와 (/=) 중 하나만 구현해도 됨

Page 28: 하스켈 프로그래밍 입문 2

타입 클래스와 C#/Java 인터페이스 비교C#/Java 하스켈

Class -

Interface Type class

Interface member Type-class member

Interface implementation Type-class instance

Page 29: 하스켈 프로그래밍 입문 2

타입 클래스의 특징• 구현을 따로 지정• 구현 타입에 대한 명시적 지정

• 여러 개의 레퍼런스 (binary method)

• 결과 값에 대한 레퍼런스 (static method)

• 멤버에 대한 디폴트 구현• 여러 개의 타입 인자

Page 30: 하스켈 프로그래밍 입문 2

타입 클래스 메소드의 종류

> :t show

(Show a) => a -> String

> :t read

(Read a) => String -> a

> :t (==)

(Eq a) => a -> a -> Bool

• instance: show

• static: read

• binary: (==)

Page 31: 하스켈 프로그래밍 입문 2

하스켈 타입클래스들

https://www.cse.iitb.ac.in/~as/fpcourse/haskell98_report/basic.html

Page 32: 하스켈 프로그래밍 입문 2

IO• pure expression 과 impure action 을 구분• IO a

• 액션을 수행하고 a 타입을 리턴• 예 ) IO Char, IO ()

Page 33: 하스켈 프로그래밍 입문 2

간단한 액션• getChar :: IO Char

• 키보드에서 문자 하나를 읽어 리턴함• putChar :: Char -> IO ()

• putChar c 는 화면에 문자 c 를 출력함• return :: a -> IO a

• return v 는 아무런 액션을 하지 않고 v 를 리턴함

Page 34: 하스켈 프로그래밍 입문 2

do 표기법do 표기법을 이용해 여러 개의 액션을 하나의 액션으로 만들 수 있음act :: IO (Char, Char)

act = do x <- getChar

getChar

y <- getChar

return (x, y)

Page 35: 하스켈 프로그래밍 입문 2

getLinegetLine :: IO String

getLine = do x <- getChar

if x == '\n' then

return []

else

do xs <- getLine

return (x:xs)

Page 36: 하스켈 프로그래밍 입문 2

putStr/putStrLnputStr :: String -> IO ()

putStr [] = return ()

putStr (x:xs) = do putChar x

putStr xs

putStrLn :: String -> IO ()

putStrLn = do putStr xs

putChar '\n'

Page 37: 하스켈 프로그래밍 입문 2

Maybe• 함수의 리턴값이 보장되어 있지 않을 때 사용> import Data.List

> :t elemIndex

elemIndex :: Eq a => a -> [a] -> Maybe Int

> elemIndex ‘b’ "abc"

Just 1

> elemIndex ‘z’ "abc"

Nothing

Page 38: 하스켈 프로그래밍 입문 2

Maybe 의 콘텍스트• Just 1 과 1

• Just "Hello" 와 "Hello"

• Just ‘a’ 와 ‘ a’

• Nothing 과 에러

Page 39: 하스켈 프로그래밍 입문 2

Maybe

safediv :: Int -> Int -> Maybe Int

safediv _ 0 = Nothing

safediv m n = Just (m `div` n)

safehead :: [a] -> Maybe a

safehead [] = Nothing

safehead xs = Just (head xs)

data Maybe a = Nothing | Just a

Page 40: 하스켈 프로그래밍 입문 2

Higher Orderdata RoseTree a = RLeaf a

| RNode [RoseTree a]

data BinTree = BLeaf a

| BNode (Pair (BinTree a))

data Pair a = MkPair a a

Page 41: 하스켈 프로그래밍 입문 2

Higher Order

data RoseTree a = RLeaf a

| RNode ([] (RoseTree a))

data BinTree = BLeaf a

| BNode (Pair (BinTree a))

— [] :: * -> * The list constructor

Syntactic Sugar 를 제거하면 ?

Page 42: 하스켈 프로그래밍 입문 2

Higher Order

data Tree k a = Leaf a

| Node (k (Tree k a))

data RoseTree a = Tree [] a

data BinTree = Tree Pair a

data AnnTree = Tree AnnPair a

data Pair a = P a a

data AnnPair a = AP String a a

변화하는 부분을 인자로 추출하면 ?• ‘a’ 는 type (a :: *)

• ‘k’ 는 type constructor (k :: * -> *)

Page 43: 하스켈 프로그래밍 입문 2

Higher Order • Maybe a

• Type

• Kind : *

• Maybe

• Type Constructor

• Kind : * -> *

Page 44: 하스켈 프로그래밍 입문 2

Functor

class Functor f where

fmap :: (a -> b) -> f a -> f b

Page 45: 하스켈 프로그래밍 입문 2

리스트에 대한 Functor> import Data.Char

> fmap (+1) [1,2,3]

[2,3,4]

> fmap toUpper "qwertyuiop"

"QWERTYUIOP"

Page 46: 하스켈 프로그래밍 입문 2

Maybe 에 대한 Functor

> fmap (+1) (Just 1)

Just 2

Page 47: 하스켈 프로그래밍 입문 2

Maybe 에 대한 Functor

instance Functor Maybe where

fmap _ Nothing = Nothing

fmap f (Just a) = Just (f a)

Page 48: 하스켈 프로그래밍 입문 2

Identity 에 대한 Functor

newtype Identity a = Identity a

Page 49: 하스켈 프로그래밍 입문 2

튜플에 대한 Functor

instance MyFunctor ((,) a) where

{- ... -}

Page 50: 하스켈 프로그래밍 입문 2

( 리뷰 ) 튜플의 생성• 두 개 인자를 받아 두 인자로 구성된 튜플을 리턴

• (,) :: a -> b -> (a, b)

Page 51: 하스켈 프로그래밍 입문 2

튜플의 partial application

> :type (,) ‘X’ True

(,) ‘X’ True :: (Char, Bool)

> :type (,) ‘X’

(,) ‘X" :: (Char, b)

Page 52: 하스켈 프로그래밍 입문 2

튜플과 타입 시그너처• (,) 를 prefix 로 함수로 사용할 수 있음• (,) 를 type constructor 로 사용할 수 있음foo :: b -> (,) Char b

foo b = (,) ‘X’ b

foo :: b -> (Char, b)

Page 53: 하스켈 프로그래밍 입문 2

튜플에 대한 Functor

instance Functor ((,) a) where

fmap f (a, b) = (a, f b)

Page 54: 하스켈 프로그래밍 입문 2

함수에 대한 Functor

instance Functor ((->) a) where

fmap f g = \x -> f (g x)

Page 55: 하스켈 프로그래밍 입문 2

IO 에 대한 Functor

> fmap (++"!") getLine

hi

"hi!"

Page 56: 하스켈 프로그래밍 입문 2

IO 에 대한 Functor

readFile "/etc/passwd"

(length . lines) `fmap` readFile "/etc/passwd"

Page 57: 하스켈 프로그래밍 입문 2

Functor 법칙• Identity 함수는 결과에 영향이 없어야 함

• fmap id === id

• 두 함수의 합성을 매핑하는 것과 각 함수의 매핑을 합성하는 것이 같아야 함• fmap (g . h) = (fmap g) . (fmap h)

Page 58: 하스켈 프로그래밍 입문 2

리프팅 (lifting) 관점에서 본 Functor

class Functor f where

fmap :: (a -> b) -> f a -> f b

class Functor f where

fmap :: (a -> b) -> (f a -> f b)

Page 59: 하스켈 프로그래밍 입문 2

콘텍스트로 이해하는 Functor

• [] functor

• 콘텍스트는 리스트• (->) functor

• 첫 번째 인자가 a 인 함수가 콘텍스트 (read-only 환경 )

• IO functor

• 사이드 이펙트가 가능한 computation 이 콘텍스트

Page 60: 하스켈 프로그래밍 입문 2

Applicative Functor

> (*) <$> Just 2 <*> Just 8

Just 16

Page 61: 하스켈 프로그래밍 입문 2

MonoidMonoid 는 다음 성질을 만족시키는 함수 •이다

1. Set(S) 는 바이너리 함수 • 에 대해 닫혀 있음• ∀ a,b ∈ S: a•b ∈ S

2. 바이너리 함수는 associative• ∀ a,b,c ∈ S: (a•b)•c = a•(b•c)

3. e 는 identity element

• ∃ e∈S: ∀ a∈S: e•a = a•e = a

Page 62: 하스켈 프로그래밍 입문 2

Monoid 예제• +, 0 은 Monoid

• *, 1 은 Monoid

• (++) 과 [] 은 Monoid

Page 63: 하스켈 프로그래밍 입문 2

Monoid> import Data.Monoid

> [1,2,3] `mappend` [4,5,6]

[1,2,3,4,5,6]

> [1,2,3] `mappend` mempty

[1,2,3]

> mempty `mappend` [1,2,3]

[1,2,3]

Page 64: 하스켈 프로그래밍 입문 2

Maybe 다시 보기• Maybe a 타입의 값아 a -> Maybe b 인 함수가 있으면 Maybe b 를 어떻게 얻을 수 있을까 ?

• bind 함수• (>>=) :: (Monad m) => ma -> (a -> m

b) -> m b

Page 65: 하스켈 프로그래밍 입문 2

bind 의 필요성f :: Int -> Maybe Int

f n = Just (n+1)

> f 1

Just 2

> f (Just 1)

ERROR!

Page 66: 하스켈 프로그래밍 입문 2

bind (>>=)> :t (>>=)

(>>=) :: Monad m => m a -> (a -> m b) -> m b

> Just 1 >>= f

Just 2

Page 67: 하스켈 프로그래밍 입문 2

Monad 타입 클래스class Monad m where

return :: a -> m a

(>>=) :: m a -> (a -> m b) -> m b

Page 68: 하스켈 프로그래밍 입문 2

>> 함수> print "foo" >>= \_ -> print "bar"

"foo"

"bar"

> print "foo" >> print "bar"

"foo"

"bar"

main = do

print "foo"

print "bar"

Page 69: 하스켈 프로그래밍 입문 2

bind 함수와 do 표기법main = do

putStrLn "Enter name:"

name <- getLine

putStrLn ("Hi " ++ name)

main = putStrLn "Enter name:" >>

getLine >>= putStrLn.("Hi " ++)

Page 70: 하스켈 프로그래밍 입문 2

모나드 법칙1. left identity

• return a >>= f ≡ f a

2. Right Identity

• m >>= return ≡ m

3. Associativity

• (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)

Page 71: 하스켈 프로그래밍 입문 2

do 표기법으로 보는 모나드 법칙

Page 72: 하스켈 프로그래밍 입문 2

합수 합성과 모나드

Page 73: 하스켈 프로그래밍 입문 2

함수 합성• f :: A -> B

• g :: B -> C

• g . f :: A -> C

Page 74: 하스켈 프로그래밍 입문 2

함수 합성의 법칙1. (f . g) . h = f . (g . h)

2. f . id = f

3. id . f = f

Page 75: 하스켈 프로그래밍 입문 2

합수 합성의 예> (take 2 . filter (>=3) . map length) ["a", "ab", "abc", "abcd", "abcde"]

[3,4]

> map (negate . abs) [5, -3, -6, 7, -3, 2, -19, 24]

[-5,-3,-6,-7,-3,-2,-19,-24]

Page 76: 하스켈 프로그래밍 입문 2

카테고리법칙1. (f . g) . h = f . (g .

h)

2. f . id = f

3. id . f = f

class Category cat where

id :: cat a a

(.) :: cat b c -> cat a b -> cat a c

instance Category (->) where

id x = x

(f . g) x = f (g x)

Page 77: 하스켈 프로그래밍 입문 2

함수 합성의 장애물

Page 78: 하스켈 프로그래밍 입문 2

Maybe 함수의 합성• f :: A -> Maybe B

• g :: B -> Maybe C

• g .f

• ERROR!

Page 79: 하스켈 프로그래밍 입문 2

Maybe 함수의 합성(<=<) :: (b -> Maybe c)

-> (a -> Maybe b)

-> (a -> Maybe c)

(f <=< g) x = case g x of

Just y -> f y

Nothing -> Nothing

return :: (a -> Maybe a)

return = Just

Page 80: 하스켈 프로그래밍 입문 2

함수 합성과의 비교id :: (a -> a)

return :: (a -> Maybe a)

(.) :: (b -> c) -> (a -> b) -> (a -> c)

(<=<) :: (b -> Maybe c) -> (a -> Maybe b) -> (a -> Maybe c)

(f . g) x = f (g x)

(f <=< g) x = f =<< (g x)

Page 81: 하스켈 프로그래밍 입문 2

Reader 함수의 합성• f :: A -> (R -> B)

• g :: B -> (R -> C)

• g . f

• ERROR!

Page 82: 하스켈 프로그래밍 입문 2

Reader 함수의 합성(<=<) :: (b -> (r -> c))

-> (a -> (r -> b))

-> (a -> (r -> c))

(f <=< g) x = \r -> f ((g x) r) r

return :: a -> (r -> a)

return a = \r -> a

Page 83: 하스켈 프로그래밍 입문 2

함수 합성과의 비교id :: (a -> a)

return :: (a -> (r-> a))

(.) :: (b -> c) -> (a -> b) -> (a -> c)

(<=<) :: (b -> (r -> c)) -> (a -> (r -> b)) -> (a -> (r -> c))

(f . g) x = f (g x)

(f <=< g) x = \r -> f ((g x) r) r

Page 84: 하스켈 프로그래밍 입문 2

Kleisli 카테고리newtype Kleisli m a b =

Kleisli { runKleisli :: a -> m b }

instance Monad m => Category (Kleisli m) where

id = Kleisli return

(Kleisli f) . (Kleisli g) = Kleisli (f <=< g)

Page 85: 하스켈 프로그래밍 입문 2

Kleisli 카테고리와 Monad

class Monad m where

(>>=) :: m a -> (a -> m b) -> m b

return :: a -> m a

• (a >>= f) = (f <=< id) a

• (f <=< g) x = f =<< (g x)

Page 86: 하스켈 프로그래밍 입문 2

Kleisli 카테고리로 보는 모나드 법칙 카테고리 법칙1. left identity

• return >=> g ≡ g

2. Right Identity

• f >=> return ≡ f

3. Associativity

• (f >=> g) >=> h ≡ f >=> (g >=> h)

(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c

모나드 법칙1. left identity

• m >>= return = m

2. Right Identity

• return x >>= f = f x

3. Associativity

• m >>= (\y -> g y >>= f) = (m >>= g) >>= f

Page 87: 하스켈 프로그래밍 입문 2

모나드의 종류• Maybe

• Either

• IO

• Reader

• Writer

• State

• Continuation

• Parser

• Pipe

• …

Page 88: 하스켈 프로그래밍 입문 2

Monad 의 함의사이드 이펙트가 있는 함수에 조합성을 주기 위한 구조

Functional Programming

Compositional Programming

Page 89: 하스켈 프로그래밍 입문 2

숙제• CIS 194 Homework 4,5,7,8 번을 풉니다

• http://www.seas.upenn.edu/~cis194/lectures.html

Page 90: 하스켈 프로그래밍 입문 2

참고 자료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

4. Slides of Functional systems in Haskell (Stanford CS240h Spring 2014)

• http://www.scs.stanford.edu/14sp-cs240h/slides/

5. Slides of Introduction to Haskell (University of Virginia CS 1501 Lectures Spring 2013)

• http://shuklan.com/haskell/index.html