Upload
kwang-yul-seo
View
574
Download
3
Embed Size (px)
Citation preview
종이접기 프로그래밍하스켈 학교 2016 년 6 월 7 일서광열
출처 : http://homeworks.tistory.com/533
리스트의 정의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
Tree 의 정의data T a = L a | B (T a) (T a)
deriving (Show)
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]) []
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
fold 의 예 : fact• 어셈블리fact0 0 = 1
fact0 n = n * fact (n - 1)
• Structured programming: control structure를 data structure와 combining form으로 교체
fact1 n = product [1..n]
fold 의 예 : 피보나치• 어셈블리fib0 0 = 0
fib0 1 = 1
fib0 n = fib0 (n - 1) * fib0 (n - 2)
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
foldL 과 foldT 의 공통점은 ?
Exprdata Expr = Const Int
| Add Expr Expr
| Mul Expr Expr
• Expr은 재귀 타입 (recursive type)
ExprF• Expr에서 재귀를 제거하면
data ExprF a = Const Int
| Add a a
| Mul a a
e.g., ExprF (ExprF (ExprF a)))
Fix
newtype Fix f = In (f (Fix f))
In :: f (Fix f) -> Fix f
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)
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)
algalg :: ExprF Int -> Int
alg (Const i) = i
alg (x `Add` y) = x + y
alg (x `Mul` y) = x * y
• Int는 캐리어 타입 (carrier type)
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)
F-Algebratype Algebra f a = f a -> a
펑터 f와 캐리어 타입 a에 대해서 alg 함수 정의
• Algebra의 구성 요소1. Functor
2. Carrier type
3. Evaluator
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
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)
Initial Algebra
• 계산 과정에서 정보의 손실 없음• initial algebra is an isomorphism
• homomoprhism
• initial algebra -> 다른 algebra
Homomorphism
• homomorphism은 하나의 carrier type을 다른 carrier type으로 보내는 함수 g 하나로 결정g :: Fix f -> a
Catamorphism
unFix :: Fix f -> f (Fix f)
unFix (In x) = x
g = alg . (fmap g) . unFix
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
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
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)
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]
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)
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)
정리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 을 다른 데이터 타입으로 일반화한 것 .
참고 자료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/