32
종종종종 종종종종종 종종종 종종 2016 종 6 종 7 종 종종종

종이접기(fold) 프로그래밍

Embed Size (px)

Citation preview

Page 1: 종이접기(fold) 프로그래밍

종이접기 프로그래밍하스켈 학교 2016 년 6 월 7 일서광열

Page 2: 종이접기(fold) 프로그래밍
Page 3: 종이접기(fold) 프로그래밍

출처 : http://homeworks.tistory.com/533

Page 4: 종이접기(fold) 프로그래밍

리스트의 정의data List a = Nil | Cons a (List a)

wrap :: a -> List a

wrap x = Cons x Nil

nil :: List a -> Bool

nil Nil = True

nil (Cons x xs) = False

Page 5: 종이접기(fold) 프로그래밍

Tree 의 정의data T a = L a | B (T a) (T a)

deriving (Show)

Page 6: 종이접기(fold) 프로그래밍

List foldfoldL :: (a -> b -> b) -> b -> List a -> b

foldL f e Nil = e

foldL f e (Cons x xs) = f x (foldL f e xs)

sumL = foldL (+) 0

productL = foldL (*) 1

reverseL = foldL (\a r -> r ++ [a]) []

Page 7: 종이접기(fold) 프로그래밍

Tree foldfoldT :: (b -> b -> b) -> (a -> b) -> (T a -> b)

foldT _ l (L a) = l a

foldT b l (B s t) = b (foldT b l s)

(foldT b l t)

productT = foldT (*) id

Page 8: 종이접기(fold) 프로그래밍

fold 의 예 : fact• 어셈블리fact0 0 = 1

fact0 n = n * fact (n - 1)

• Structured programming: control structure를 data structure와 combining form으로 교체

fact1 n = product [1..n]

Page 9: 종이접기(fold) 프로그래밍

fold 의 예 : 피보나치• 어셈블리fib0 0 = 0

fib0 1 = 1

fib0 n = fib0 (n - 1) * fib0 (n - 2)

Page 10: 종이접기(fold) 프로그래밍

fold 의 예 : 피보나치fibT :: Integer

-> T Integer

fibT 0 = L 0

fibT 1 = L 1

fibT n = B (fibT (n - 1))

(fibT (n - 2))

sumT :: T Integer

-> Integer

sumT = foldT (+) id

fib1 = Integer

-> Integer

fib1 = sumT . fibT

Page 11: 종이접기(fold) 프로그래밍

foldL 과 foldT 의 공통점은 ?

Page 12: 종이접기(fold) 프로그래밍

Exprdata Expr = Const Int

| Add Expr Expr

| Mul Expr Expr

• Expr은 재귀 타입 (recursive type)

Page 13: 종이접기(fold) 프로그래밍

ExprF• Expr에서 재귀를 제거하면

data ExprF a = Const Int

| Add a a

| Mul a a

e.g., ExprF (ExprF (ExprF a)))

Page 14: 종이접기(fold) 프로그래밍

Fix

newtype Fix f = In (f (Fix f))

In :: f (Fix f) -> Fix f

Page 15: 종이접기(fold) 프로그래밍

Fix 로 정의한 Exprdata Expr = Fix ExprF

val :: Fix ExprF

val = In (Const 12)

testExpr = In $ (In $ (In $ Const 2) `Add`

(In $ Const 3)) `Mul` (In $ Const 4)

Page 16: 종이접기(fold) 프로그래밍

ExprF Functorinstance Functor ExprF where

fmap eval (Const i) = Const i

fmap eval (left `Add` right) =

(eval left) `Add` (eval right)

fmap eval (left `Mul` right) =

(eval left) `Mul` (eval right)

Page 17: 종이접기(fold) 프로그래밍

algalg :: ExprF Int -> Int

alg (Const i) = i

alg (x `Add` y) = x + y

alg (x `Mul` y) = x * y

• Int는 캐리어 타입 (carrier type)

Page 18: 종이접기(fold) 프로그래밍

alg’alg' :: ExprF String -> String

alg' (Const i) = [chr (ord 'a' + i)]

alg' (x `Add` y) = x ++ y

alg' (x `Mul` y) =

concat [[a,b] | a <- x, b <- y]

• String은 캐리어 타입 (carrier type)

Page 19: 종이접기(fold) 프로그래밍

F-Algebratype Algebra f a = f a -> a

펑터 f와 캐리어 타입 a에 대해서 alg 함수 정의

• Algebra의 구성 요소1. Functor

2. Carrier type

3. Evaluator

Page 20: 종이접기(fold) 프로그래밍

Algebratype SimpleA = Algebra ExprF Int

-- alg :: SimpleA

alg :: ExprF Int -> Int

alg (Const i) = i

alg (x `Add` y) = x + y

alg (x `Mul` y) = x * y

Page 21: 종이접기(fold) 프로그래밍

Initial Algebra• Int나 String 대신에 (Fix ExprF)를 캐리어 타입으로 사용type ExprInitAlg = Algebra ExprF (Fix ExprF)

-- ex_init_alg :: ExprInitAlg

ex_init_alg :: ExprF (Fix ExprF) -> Fix ExprF

ex_init_alg = In

• 이 함수는 (ExprF Expr)을 주면 Expr을 리턴함> ex_init_alg $ Add (In $ Const 2) (In $ Const 3)

In $ Add (In $ Const 2) (In $ Const 3)

Page 22: 종이접기(fold) 프로그래밍

Initial Algebra

• 계산 과정에서 정보의 손실 없음• initial algebra is an isomorphism

• homomoprhism

• initial algebra -> 다른 algebra

Page 23: 종이접기(fold) 프로그래밍

Homomorphism

• homomorphism은 하나의 carrier type을 다른 carrier type으로 보내는 함수 g 하나로 결정g :: Fix f -> a

Page 24: 종이접기(fold) 프로그래밍

Catamorphism

unFix :: Fix f -> f (Fix f)

unFix (In x) = x

g = alg . (fmap g) . unFix

Page 25: 종이접기(fold) 프로그래밍

Catamorphismg :: Fix f -> a

g = alg . (fmap g) . unFix

• g = cata alg 로 정의하면cata :: Functor f => (f a -> a) -> Fix f -> a

cata alg = alg . fmap (cata alg) . unFix

Page 26: 종이접기(fold) 프로그래밍

cata 를 이용한 eval 의 정의type SimpleA = Algebra ExprF Int

alg :: SimpleA

alg (Const i) = i

alg (x `Add` y) = x + y

alg (x `Mul` y) = x * y

cata :: Functor f => (f a -> a) -> Fix f -> a

cata alg = alg . fmap (cata alg) . unFix

eval :: Fix ExprF -> Int

eval = alg . fmap eval . unFix

Page 27: 종이접기(fold) 프로그래밍

List 다시 보기data ListF a b = Nil | Cons a b

instance Functor (ListF a) where

fmap f Nil = Nil

fmap f (Cons e x) = Cons e (f x)

Page 28: 종이접기(fold) 프로그래밍

algSumalgSum :: ListF Int Int -> Int

algSum Nil = 0

algSum (Cons e acc) = e + acc

lst :: Fix (ListF Int)

lst = In $ Cons 2 (In $ Cons 3 (In $ Cons 4 (In Nil)))

cata algSum lst

== foldr (\e acc -> e + acc) 0 [2..4]

Page 29: 종이접기(fold) 프로그래밍

Tree 다시 보기data TreeF a b = L a | B b b

deriving (Show)

instance Functor (TreeF a) where

fmap f (L a) = L a

fmap f (B x y) = B (f x) (f y)

Page 30: 종이접기(fold) 프로그래밍

algSumalgSum :: TreeF Int Int -> Int

algSum (L a) = a

algSum (B x y) = x + y

> cata algSum tree

6

type IntTree = Fix (TreeF Int)

l :: Int -> IntTree

l x = In (L x)

b :: IntTree -> IntTree -> IntTree

b x y = In (x `B` y)

tree :: IntTree

tree = ((l 1) `b` (l 2)) `b` (l 3)

Page 31: 종이접기(fold) 프로그래밍

정리1. 재귀 함수가 일반 함수의 fixed point 로 정의되는 것처럼 재귀 타입은 일반 타입의 fixed point 로 정의2. functor 는 nested data structure 에 대한 recursive evaluation 을 지원3. F-algebra 는 1) functor f, 2) carrier type a, 3) f a -> a 로 가는 함수로 정의4. initial algebra 는 해당 functor 로 정의되는 모든 algebra 로 매핑 가능 . 이 algebra 의 carrier type 은 functor 의 fixed point

5. initial algebra 와 다른 algebra 사이의 유일한 mapping 은 catamorphism 으로 생성

6. catamorphism 은 simple algebra 를 받아서 nested data structure에 대한 recursive evaluator 를 제공 . 이는 list folding 을 다른 데이터 타입으로 일반화한 것 .

Page 32: 종이접기(fold) 프로그래밍

참고 자료1. Origami programming, Jeremy Gibbons

• https://www.cs.ox.ac.uk/jeremy.gibbons/publications/origami.pdf

2. Understanding F-Algebras

• https://bartoszmilewski.com/2013/06/10/understanding-f-algebras/