하스켈 프로그래밍
입문 2
하스켈 학교 2016년 5월 21일
서광열
함수 합성
(.): 두 함수를 인자로 받아 두 함수의 합성 함수를 리턴
함
(.) :: (b -> c) -> (a -> b) -> (a -> c)
f . g = x -> f (g x)
odd :: Int -> Bool
odd = not . even
$를 이용한 함수 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를 호출함
Type synonym
• type String = [Char]
• type Pos = (Int, Int)
origin :: Pos
origin = (0, 0)
left :: Pos -> Pos
left (x, y) = (x-1, y)
Type synonym
• type Pair a = (a, a)
mult :: Pair Int -> Int
mult (m, n) = m *n
copy :: a -> Pair a
copy x = (x, x)
Type synonym
• Can be nested
• type Trans = Pos -> Pos
• Can't be recursive
• type Tree = (Int, [Tree])
Algebraic Data Type
Algebraic Data Type
data Answer = Yes | No | Unknown
answers :: [Answer]
answers = [Yes, No, Unknown]
flip :: Answer -> Answer
flip Yes = No
flip No = Yes
flip Unknown = Unknown
Algebraic Data Type
data 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
재귀 타입 (Succ)
data Nat = Zero | Succ Nat
Zero -- 0
Succ Zero -- 1
Succ (Succ Zero) -- 2
Succ (Succ (Succ Zero)) -- 3
재귀 타입 (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))
재귀 타입 (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)
재귀 타입 (Succ)
add (Succ (Succ Zero)) (Succ Zero)
= Succ (add (Succ Zero) (Succ Zero)
= Succ (Succ (add Zero (Succ Zero))
= Succ (Succ (Succ Zero))
재귀 타입(Expr)
data Expr = Val Int
| Add Expr Expr
| Mul Expr Expr
-- 1 + (2 * 3)
Add (Val 1) (Mul (Val 2) (Val 3))
재귀 타입 (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
재귀 타입 (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))
재귀 타입 (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
재귀 타입 (Binary Tree)
flatten :: Tree a -> [a]
flatten (Leaf x) = [x]
flatten (Node l x r) = flatten l
++ [x]
++ flatten r
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)
Record
data Person = Person { firstName :: String
, lastName :: String
, age :: Int
}
• 각 필드에 이름을 부여
• 필드 이름은 해당 필드 값을 꺼내는 getter 함수가 됨
Record 생성 및 getter
> :t Person
Person :: String -> String -> Int -> Person
> :t firstName
firstName :: Person -> String
> :t lastName
lastName :: Person -> String
> :t age
age :: Person -> Int
Record
> let p = Person { firstName = "Kwang", lastName =
"Seo", age = 20 }
> firstName p
"Kwang"
> age p
20
Record 패턴 매칭
fullName :: Person -> String
fullName (Person {firstName = fn, lastName = ln}) =
fn ++ " " ++ ln
deriving
• Show, Eq 등의 타입 클래스 인스턴스를 자동으로
생성
data Expr = Const Int
| Add Expr Expr
deriving (Eq, Show)
타입 클래스
class Eq a where
(==) :: a -> a -> Bool
타입 클래스
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'
타입 클래스
class Eq a where
(==), (/=) :: a -> a -> Bool
x/=y = not (x==y)
x==y = not (x/=y)
(==)와 (/=) 중 하나만 구현해도 됨
타입 클래스와 C#/Java 인
터페이스 비교
C#/Java 하스켈
Class -
Interface Type class
Interface member Type-class member
Interface implementation Type-class instance
타입 클래스의 특징
• 구현을 따로 지정
• 구현 타입에 대한 명시적 지정
• 여러 개의 레퍼런스 (binary method)
• 결과 값에 대한 레퍼런스 (static method)
• 멤버에 대한 디폴트 구현
• 여러 개의 타입 인자
타입 클래스 메소드의 종
류
> :t show
(Show a) => a -> String
> :t read
(Read a) => String -> a
> :t (==)
(Eq a) => a -> a -> Bool
• instance: show
• static: read
• binary: (==)
하스켈 타입클래스들
https://www.cse.iitb.ac.in/~as/fpcourse/haskell98_report/basic.htm
IO
• pure expression과 impure action을 구분
• IO a
• 액션을 수행하고 a 타입을 리턴
• 예) IO Char, IO ()
간단한 액션
• getChar :: IO Char
• 키보드에서 문자 하나를 읽어 리턴함
• putChar :: Char -> IO ()
• putChar c는 화면에 문자 c를 출력함
• return :: a -> IO a
• return v는 아무런 액션을 하지 않고 v를 리턴함
do 표기법
do 표기법을 이용해 여러 개의 액션을 하나의 액션으로
만들 수 있음
act :: IO (Char, Char)
act = do x <- getChar
getChar
y <- getChar
return (x, y)
getLine
getLine :: IO String
getLine = do x <- getChar
if x == 'n' then
return []
else
do xs <- getLine
return (x:xs)
putStr/putStrLn
putStr :: String -> IO ()
putStr [] = return ()
putStr (x:xs) = do putChar x
putStr xs
putStrLn :: String -> IO ()
putStrLn = do putStr xs
putChar 'n'
Maybe
• 함수의 리턴값이 보장되어 있지 않을 때 사용
> import Data.List
> :t elemIndex
elemIndex :: Eq a => a -> [a] -> Maybe Int
> elemIndex ‘b’ "abc"
Just 1
> elemIndex ‘z’ "abc"
Nothing
Maybe의 콘텍스트
• Just 1과 1
• Just "Hello"와 "Hello"
• Just ‘a’와 ‘a’
• Nothing과 에러
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
Higher Order
data RoseTree a = RLeaf a
| RNode [RoseTree a]
data BinTree = BLeaf a
| BNode (Pair (BinTree a))
data Pair a = MkPair a a
Higher Order
data RoseTree a = RLeaf a
| RNode ([] (RoseTree a))
data BinTree = BLeaf a
| BNode (Pair (BinTree a))
— [] :: * -> * The list constructor
Syntactic Sugar를 제거하면?
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 :: * -> *)
Higher Order
• Maybe a
• Type
• Kind : *
• Maybe
• Type Constructor
• Kind : * -> *
Functor
class Functor f where
fmap :: (a -> b) -> f a -> f b
리스트에 대한 Functor
> import Data.Char
> fmap (+1) [1,2,3]
[2,3,4]
> fmap toUpper "qwertyuiop"
"QWERTYUIOP"
Maybe에 대한 Functor
> fmap (+1) (Just 1)
Just 2
Maybe에 대한 Functor
instance Functor Maybe where
fmap _ Nothing = Nothing
fmap f (Just a) = Just (f a)
Identity에 대한 Functor
newtype Identity a = Identity a
튜플에 대한 Functor
instance MyFunctor ((,) a) where
{- ... -}
(리뷰) 튜플의 생성
• 두 개 인자를 받아 두 인자로 구성된 튜플을 리턴
• (,) :: a -> b -> (a, b)
튜플의 partial application
> :type (,) ‘X’ True
(,) ‘X’ True :: (Char, Bool)
> :type (,) ‘X’
(,) ‘X" :: (Char, b)
튜플과 타입 시그너처
• (,)를 prefix로 함수로 사용할 수 있음
• (,)를 type constructor로 사용할 수 있음
foo :: b -> (,) Char b
foo b = (,) ‘X’ b
foo :: b -> (Char, b)
튜플에 대한 Functor
instance Functor ((,) a) where
fmap f (a, b) = (a, f b)
함수에 대한 Functor
instance Functor ((->) a) where
fmap f g = x -> f (g x)
IO에 대한 Functor
> fmap (++"!") getLine
hi
"hi!"
IO에 대한 Functor
readFile "/etc/passwd"
(length . lines) `fmap` readFile "/etc/passwd"
Functor 법칙
• Identity 함수는 결과에 영향이 없어야 함
• fmap id === id
• 두 함수의 합성을 매핑하는 것과 각 함수의 매핑을
합성하는 것이 같아야 함
• fmap (g . h) = (fmap g) . (fmap h)
리프팅(lifting) 관점에서 본
Functor
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Functor f where
fmap :: (a -> b) -> (f a -> f b)
콘텍스트로 이해하는
Functor
• [] functor
• 콘텍스트는 리스트
• (->) functor
• 첫 번째 인자가 a인 함수가 콘텍스트 (read-only 환
경)
• IO functor
• 사이드 이펙트가 가능한 computation이 콘텍스트
Applicative Functor
> (*) <$> Just 2 <*> Just 8
Just 16
Monoid
Monoid는 다음 성질을 만족시키는 함수 •이다
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
Monoid 예제
• +, 0은 Monoid
• *, 1은 Monoid
• (++)과 []은 Monoid
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]
Maybe 다시 보기
• Maybe a 타입의 값아 a -> Maybe b인 함수가 있으면
Maybe b를 어떻게 얻을 수 있을까?
• bind 함수
• (>>=) :: (Monad m) => ma -> (a -> m b) -> m b
bind의 필요성
f :: Int -> Maybe Int
f n = Just (n+1)
> f 1
Just 2
> f (Just 1)
ERROR!
bind (>>=)
> :t (>>=)
(>>=) :: Monad m => m a -> (a -> m b) -> m b
> Just 1 >>= f
Just 2
Monad 타입 클래스
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
>> 함수
> print "foo" >>= _ -> print "bar"
"foo"
"bar"
> print "foo" >> print "bar"
"foo"
"bar"
main = do
print "foo"
print "bar"
bind 함수와 do 표기법
main = do
putStrLn "Enter name:"
name <- getLine
putStrLn ("Hi " ++ name)
main = putStrLn "Enter name:" >>
getLine >>= putStrLn.("Hi " ++)
모나드 법칙
1. left identity
• return a >>= f ≡ f a
2. Right Identity
• m >>= return ≡ m
3. Associativity
• (m >>= f) >>= g ≡ m >>= (x -> f x >>= g)
do 표기법으로 보는 모나드
법칙
합수 합성과 모나드
함수 합성
• f :: A -> B
• g :: B -> C
• g . f :: A -> C
함수 합성의 법칙
1. (f . g) . h = f . (g . h)
2. f . id = f
3. id . f = f
합수 합성의 예
> (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]
카테고리
법칙
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)
함수 합성의 장애물
Maybe 함수의 합성
• f :: A -> Maybe B
• g :: B -> Maybe C
• g .f
• ERROR!
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
함수 합성과의 비교
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)
Reader 함수의 합성
• f :: A -> (R -> B)
• g :: B -> (R -> C)
• g . f
• ERROR!
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
함수 합성과의 비교
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
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)
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)
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
모나드의 종류
• Maybe
• Either
• IO
• Reader
• Writer
• State
• Continuation
• Parser
• Pipe
• …
Monad의 함의
사이드 이펙트가 있는 함수에 조합성을 주기 위한 구조
Functional Programming
Compositional Programming
숙제
• CIS 194 Homework 4,5,7,8번을 풉니다
• http://www.seas.upenn.edu/~cis194/lectures.html
참고 자료
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

하스켈 프로그래밍 입문 2

  • 1.
    하스켈 프로그래밍 입문 2 하스켈학교 2016년 5월 21일 서광열
  • 2.
    함수 합성 (.): 두함수를 인자로 받아 두 함수의 합성 함수를 리턴 함 (.) :: (b -> c) -> (a -> b) -> (a -> c) f . g = x -> f (g x) odd :: Int -> Bool odd = not . even
  • 3.
    $를 이용한 함수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를 호출함
  • 4.
    Type synonym • typeString = [Char] • type Pos = (Int, Int) origin :: Pos origin = (0, 0) left :: Pos -> Pos left (x, y) = (x-1, y)
  • 5.
    Type synonym • typePair a = (a, a) mult :: Pair Int -> Int mult (m, n) = m *n copy :: a -> Pair a copy x = (x, x)
  • 6.
    Type synonym • Canbe nested • type Trans = Pos -> Pos • Can't be recursive • type Tree = (Int, [Tree])
  • 7.
  • 8.
    Algebraic Data Type dataAnswer = Yes | No | Unknown answers :: [Answer] answers = [Yes, No, Unknown] flip :: Answer -> Answer flip Yes = No flip No = Yes flip Unknown = Unknown
  • 9.
    Algebraic Data Type dataShape = 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
  • 10.
    재귀 타입 (Succ) dataNat = Zero | Succ Nat Zero -- 0 Succ Zero -- 1 Succ (Succ Zero) -- 2 Succ (Succ (Succ Zero)) -- 3
  • 11.
    재귀 타입 (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))
  • 12.
    재귀 타입 (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)
  • 13.
    재귀 타입 (Succ) add(Succ (Succ Zero)) (Succ Zero) = Succ (add (Succ Zero) (Succ Zero) = Succ (Succ (add Zero (Succ Zero)) = Succ (Succ (Succ Zero))
  • 14.
    재귀 타입(Expr) data Expr= Val Int | Add Expr Expr | Mul Expr Expr -- 1 + (2 * 3) Add (Val 1) (Mul (Val 2) (Val 3))
  • 15.
    재귀 타입 (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
  • 16.
    재귀 타입 (BinaryTree) 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))
  • 17.
    재귀 타입 (BinaryTree) 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
  • 18.
    재귀 타입 (BinaryTree) flatten :: Tree a -> [a] flatten (Leaf x) = [x] flatten (Node l x r) = flatten l ++ [x] ++ flatten r
  • 19.
    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)
  • 20.
    Record data Person =Person { firstName :: String , lastName :: String , age :: Int } • 각 필드에 이름을 부여 • 필드 이름은 해당 필드 값을 꺼내는 getter 함수가 됨
  • 21.
    Record 생성 및getter > :t Person Person :: String -> String -> Int -> Person > :t firstName firstName :: Person -> String > :t lastName lastName :: Person -> String > :t age age :: Person -> Int
  • 22.
    Record > let p= Person { firstName = "Kwang", lastName = "Seo", age = 20 } > firstName p "Kwang" > age p 20
  • 23.
    Record 패턴 매칭 fullName:: Person -> String fullName (Person {firstName = fn, lastName = ln}) = fn ++ " " ++ ln
  • 24.
    deriving • Show, Eq등의 타입 클래스 인스턴스를 자동으로 생성 data Expr = Const Int | Add Expr Expr deriving (Eq, Show)
  • 25.
    타입 클래스 class Eqa where (==) :: a -> a -> Bool
  • 26.
    타입 클래스 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'
  • 27.
    타입 클래스 class Eqa where (==), (/=) :: a -> a -> Bool x/=y = not (x==y) x==y = not (x/=y) (==)와 (/=) 중 하나만 구현해도 됨
  • 28.
    타입 클래스와 C#/Java인 터페이스 비교 C#/Java 하스켈 Class - Interface Type class Interface member Type-class member Interface implementation Type-class instance
  • 29.
    타입 클래스의 특징 •구현을 따로 지정 • 구현 타입에 대한 명시적 지정 • 여러 개의 레퍼런스 (binary method) • 결과 값에 대한 레퍼런스 (static method) • 멤버에 대한 디폴트 구현 • 여러 개의 타입 인자
  • 30.
    타입 클래스 메소드의종 류 > :t show (Show a) => a -> String > :t read (Read a) => String -> a > :t (==) (Eq a) => a -> a -> Bool • instance: show • static: read • binary: (==)
  • 31.
  • 32.
    IO • pure expression과impure action을 구분 • IO a • 액션을 수행하고 a 타입을 리턴 • 예) IO Char, IO ()
  • 33.
    간단한 액션 • getChar:: IO Char • 키보드에서 문자 하나를 읽어 리턴함 • putChar :: Char -> IO () • putChar c는 화면에 문자 c를 출력함 • return :: a -> IO a • return v는 아무런 액션을 하지 않고 v를 리턴함
  • 34.
    do 표기법 do 표기법을이용해 여러 개의 액션을 하나의 액션으로 만들 수 있음 act :: IO (Char, Char) act = do x <- getChar getChar y <- getChar return (x, y)
  • 35.
    getLine getLine :: IOString getLine = do x <- getChar if x == 'n' then return [] else do xs <- getLine return (x:xs)
  • 36.
    putStr/putStrLn putStr :: String-> IO () putStr [] = return () putStr (x:xs) = do putChar x putStr xs putStrLn :: String -> IO () putStrLn = do putStr xs putChar 'n'
  • 37.
    Maybe • 함수의 리턴값이보장되어 있지 않을 때 사용 > import Data.List > :t elemIndex elemIndex :: Eq a => a -> [a] -> Maybe Int > elemIndex ‘b’ "abc" Just 1 > elemIndex ‘z’ "abc" Nothing
  • 38.
    Maybe의 콘텍스트 • Just1과 1 • Just "Hello"와 "Hello" • Just ‘a’와 ‘a’ • Nothing과 에러
  • 39.
    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
  • 40.
    Higher Order data RoseTreea = RLeaf a | RNode [RoseTree a] data BinTree = BLeaf a | BNode (Pair (BinTree a)) data Pair a = MkPair a a
  • 41.
    Higher Order data RoseTreea = RLeaf a | RNode ([] (RoseTree a)) data BinTree = BLeaf a | BNode (Pair (BinTree a)) — [] :: * -> * The list constructor Syntactic Sugar를 제거하면?
  • 42.
    Higher Order data Treek 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 :: * -> *)
  • 43.
    Higher Order • Maybea • Type • Kind : * • Maybe • Type Constructor • Kind : * -> *
  • 44.
    Functor class Functor fwhere fmap :: (a -> b) -> f a -> f b
  • 45.
    리스트에 대한 Functor >import Data.Char > fmap (+1) [1,2,3] [2,3,4] > fmap toUpper "qwertyuiop" "QWERTYUIOP"
  • 46.
    Maybe에 대한 Functor >fmap (+1) (Just 1) Just 2
  • 47.
    Maybe에 대한 Functor instanceFunctor Maybe where fmap _ Nothing = Nothing fmap f (Just a) = Just (f a)
  • 48.
    Identity에 대한 Functor newtypeIdentity a = Identity a
  • 49.
    튜플에 대한 Functor instanceMyFunctor ((,) a) where {- ... -}
  • 50.
    (리뷰) 튜플의 생성 •두 개 인자를 받아 두 인자로 구성된 튜플을 리턴 • (,) :: a -> b -> (a, b)
  • 51.
    튜플의 partial application >:type (,) ‘X’ True (,) ‘X’ True :: (Char, Bool) > :type (,) ‘X’ (,) ‘X" :: (Char, b)
  • 52.
    튜플과 타입 시그너처 •(,)를 prefix로 함수로 사용할 수 있음 • (,)를 type constructor로 사용할 수 있음 foo :: b -> (,) Char b foo b = (,) ‘X’ b foo :: b -> (Char, b)
  • 53.
    튜플에 대한 Functor instanceFunctor ((,) a) where fmap f (a, b) = (a, f b)
  • 54.
    함수에 대한 Functor instanceFunctor ((->) a) where fmap f g = x -> f (g x)
  • 55.
    IO에 대한 Functor >fmap (++"!") getLine hi "hi!"
  • 56.
    IO에 대한 Functor readFile"/etc/passwd" (length . lines) `fmap` readFile "/etc/passwd"
  • 57.
    Functor 법칙 • Identity함수는 결과에 영향이 없어야 함 • fmap id === id • 두 함수의 합성을 매핑하는 것과 각 함수의 매핑을 합성하는 것이 같아야 함 • fmap (g . h) = (fmap g) . (fmap h)
  • 58.
    리프팅(lifting) 관점에서 본 Functor classFunctor f where fmap :: (a -> b) -> f a -> f b class Functor f where fmap :: (a -> b) -> (f a -> f b)
  • 59.
    콘텍스트로 이해하는 Functor • []functor • 콘텍스트는 리스트 • (->) functor • 첫 번째 인자가 a인 함수가 콘텍스트 (read-only 환 경) • IO functor • 사이드 이펙트가 가능한 computation이 콘텍스트
  • 60.
    Applicative Functor > (*)<$> Just 2 <*> Just 8 Just 16
  • 61.
    Monoid Monoid는 다음 성질을만족시키는 함수 •이다 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
  • 62.
    Monoid 예제 • +,0은 Monoid • *, 1은 Monoid • (++)과 []은 Monoid
  • 63.
    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]
  • 64.
    Maybe 다시 보기 •Maybe a 타입의 값아 a -> Maybe b인 함수가 있으면 Maybe b를 어떻게 얻을 수 있을까? • bind 함수 • (>>=) :: (Monad m) => ma -> (a -> m b) -> m b
  • 65.
    bind의 필요성 f ::Int -> Maybe Int f n = Just (n+1) > f 1 Just 2 > f (Just 1) ERROR!
  • 66.
    bind (>>=) > :t(>>=) (>>=) :: Monad m => m a -> (a -> m b) -> m b > Just 1 >>= f Just 2
  • 67.
    Monad 타입 클래스 classMonad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  • 68.
    >> 함수 > print"foo" >>= _ -> print "bar" "foo" "bar" > print "foo" >> print "bar" "foo" "bar" main = do print "foo" print "bar"
  • 69.
    bind 함수와 do표기법 main = do putStrLn "Enter name:" name <- getLine putStrLn ("Hi " ++ name) main = putStrLn "Enter name:" >> getLine >>= putStrLn.("Hi " ++)
  • 70.
    모나드 법칙 1. leftidentity • return a >>= f ≡ f a 2. Right Identity • m >>= return ≡ m 3. Associativity • (m >>= f) >>= g ≡ m >>= (x -> f x >>= g)
  • 71.
    do 표기법으로 보는모나드 법칙
  • 72.
  • 73.
    함수 합성 • f:: A -> B • g :: B -> C • g . f :: A -> C
  • 74.
    함수 합성의 법칙 1.(f . g) . h = f . (g . h) 2. f . id = f 3. id . f = f
  • 75.
    합수 합성의 예 >(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]
  • 76.
    카테고리 법칙 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)
  • 77.
  • 78.
    Maybe 함수의 합성 •f :: A -> Maybe B • g :: B -> Maybe C • g .f • ERROR!
  • 79.
    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
  • 80.
    함수 합성과의 비교 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)
  • 81.
    Reader 함수의 합성 •f :: A -> (R -> B) • g :: B -> (R -> C) • g . f • ERROR!
  • 82.
    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
  • 83.
    함수 합성과의 비교 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
  • 84.
    Kleisli 카테고리 newtype Kleislim a b = Kleisli { runKleisli :: a -> m b } instance Monad m => Category (Kleisli m) where id = Kleisli return (Kleisli f) . (Kleisli g) = Kleisli (f <=< g)
  • 85.
    Kleisli 카테고리와 Monad classMonad m where (>>=) :: m a -> (a -> m b) -> m b return :: a -> m a • (a >>= f) = (f <=< id) a • (f <=< g) x = f =<< (g x)
  • 86.
    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
  • 87.
    모나드의 종류 • Maybe •Either • IO • Reader • Writer • State • Continuation • Parser • Pipe • …
  • 88.
    Monad의 함의 사이드 이펙트가있는 함수에 조합성을 주기 위한 구조 Functional Programming Compositional Programming
  • 89.
    숙제 • CIS 194Homework 4,5,7,8번을 풉니다 • http://www.seas.upenn.edu/~cis194/lectures.html
  • 90.
    참고 자료 1. Slidesof 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