하스켈 프로그래밍 입문 4

36
하하하 하하하하하 하하 4 하하하 하하 2016 하 6 하 4 하 하하하

Upload: kwang-yul-seo

Post on 17-Jan-2017

256 views

Category:

Engineering


5 download

TRANSCRIPT

하스켈 프로그래밍입문 4하스켈 학교 2016 년 6 월 4 일서광열

Functor

class Functor f where

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

Functor 의 한계> fmap (+1) [1,2,3]

[2,3,4]

> fmap (+) [1,2,3] [4,5,6]

ERROR!

Applicative Functor

class Functor f => Applicative f where

pure :: a -> f a

(<*>) :: f (a -> b) -> f a -> f b

Functor vs Applicative Functor

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

[2,3,4]

> pure (+) <*> [1,2,3] <*> [4,5,6]

[5,6,7,6,7,8,7,8,9]

Applicative Maybe 정의instance Applicative Maybe where

pure = Just

Nothing <*> _ = Nothing

(Just f) <*> x = fmap f x

Applicative Maybe 예제> Just (+3) <*> Just 4

Just 7

> pure (+3) <*> Nothing

Nothing

> pure (+) <*> Just 3 <*> Just 4

Just 7

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

Just 16

Applicative [] 의 정의instance Applicative [] where

pure x = [x]

fs <*> xs = [f x | f <- fs, x <- xs]

Applicative [] 예제> (*) <$> [1,2,3] <*> [1,0,0,1]

[1,0,0,1,2,0,0,2,3,0,0,3]

> pure 7

7

> pure 7 :: [Int]

[7]

Applicative IO 의 정의instance Applicative IO where

pure = return

a <*> b = do f <- a

x <- b

return (f x)

Applicative IO 예제main = do

a <- (++) <$> getLine <*> getLine

putStrLn a

liftA2• 일반 함수를 두 개의 functor 에 쉽게 apply 할 수 있게 해주는 함수liftA2 :: (Applicative f) =>

(a -> b -> c) ->

f a -> f b -> f c

liftA2 f a b = f <$> a <*> b

liftA2 예제> (+) <$> Just 3 <*> Just 4

Just 7

> liftA2 (+) (Just 3) (Just 4)

Just 7

Applicative Functor 법칙1. pure f <*> x = fmap f x

2. pure id <*> v = v

3. pure (.) <*> u <*> v <*> w = u <*> (v <*> w)

4. pure f <*> pure x = pure (f x)

5. u <*> pure y = pure ($ y) <*> u

Foldable

• 리스트 foldr 의 일반화• foldr :: (a -> b -> b) -> b -> [a] -> b

mconcat• foldr f z [a, b, c]

• a `f` (b `f` (c `f` z))

• f = (<>), z = mempty

• a <> (b <> (c <> mempty))

mconcat :: Monoid m => [m] -> m

mconcat = foldr mappend mempty

mconcat 예제

> mconcat ["Tree", "fingers"]

"Treefingers"

foldMap• mconcat 에서 Monoid 인스턴스 제약을 제거

foldMap :: Monoid m => (a -> m) -> [a] -> m

foldMap g = mconcat . fmap g

foldMap 의 예제

> foldMap Sum [1..10]

Sum {getSum = 55}

foldr 다시 보기• foldr :: (a -> (b -> b)) -> b -> [a] -> b

• b -> b 는 composition 에 대해 Monoid• mappend = (.)• mempty = id

newtype Endo b = Endo { appEndo :: b -> b }

instance Monoid Endo where

mempty = Endo id

Endo g `mappend` Endo f = Endo (g . f)

foldComposingfoldComposing :: (a -> (b -> b)) -> [a] -> Endo b

foldComposing f = foldMap (Endo . f)

foldr :: (a -> (b -> b)) -> b -> [a] -> b

foldr f z xs = appEndo (foldComposing f xs) z

• foldr 을 foldMap 을 이용해 정의할 수 있다는 의미

foldComposing 연산1. foldComposing (+) [1, 2, 3]

2. foldMap (Endo . (+)) [1, 2, 3]

3. mconcat (fmap (Endo . (+)) [1, 2, 3])

4. mconcat (fmap Endo [(+1), (+2), (+3)])

5. mconcat [Endo (+1), Endo (+2), Endo (+3)]

6. Endo ((+1) . (+2) . (+3))

7. Endo (+6)

Foldable 타입 클래스class Foldable t where

foldMap :: Monoid m => (a -> m) -> t a -> m

foldr :: (a -> b -> b) -> b -> t a -> b

• foldMap 과 foldr 둘 중 하나만 정의하면 됨

Foldable 타입 클래스 함수• fold :: Monoid m => t m ->

m -- generalised mconcat

• foldr' :: (a -> b -> b) -> b -> t a -> b

• foldl :: (b -> a -> b) -> b -> t a -> b

• foldl' :: (b -> a -> b) -> b -> t a -> b

• foldr1 :: (a -> a -> a) -> t a -> a

• foldl1 :: (a -> a -> a) -> t a -> a

• toList :: t a -> [a]• null :: t a -> Bool• length :: t a -> Int• elem :: Eq a => a -> t a ->

Bool• maximum :: Ord a => t a -> a• minimum :: Ord a => t a -> a• sum :: Num a => t a -> a• product :: Num a => t a -> a

Data.Foldable 함수• traverse_ :: (Foldable t, Applicative f) => (a -> f

b) -> t a -> f ()

• Map each element of a structure to an action, evaluate these actions from left to right, and ignore the results. For a version that doesn't ignore the results see traverse.

• mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()

• Map each element of a structure to a monadic action, evaluate these actions from left to right, and ignore the results. For a version that doesn't ignore the results see mapM.

Foldable 예제> import qualified Data.Map as M

> let testMap = M.fromList $ zip [0..] ["Yesterday","I","woke","up","sucking","a","lemon"]

> length testMap

7

> sum . fmap length $ testMap

29

> elem "lemon" testMap

True

> foldr1 (\x y -> x ++ (' ' : y)) testMap

"Yesterday I woke up sucking a lemon"

Foldable 예제> import Data.Foldable

> traverse_ putStrLn testMap

Yesterday

I

woke

up

sucking

a

lemon

Traversable

deleteIfNegative :: (Num a, Ord a) => a -> Maybe a

deleteIfNegative x = if x < 0 then Nothing else Just x

rejectWithNegatives :: (Num a, Ord a) => [a] -> Maybe [a]

• deleteIfNegative 를 이용해서 rejectWithNegatives 를 구현하려면 ?

> let testList = [-5,3,2,-1,0]

> fmap deleteIfNegative testList

[Nothing,Just 3,Just 2,Nothing,Just 0]

No!!

Traversable 타입 클래스class (Functor t, Foldable t) => Traversable t where

traverse :: Applicative f => (a -> f b) -> t a -> f (t b)

sequenceA :: Applicative f => t (f a) -> f (t a)

-- These methods have default definitions.

-- They are merely specialised versions of the other two.

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

sequence :: Monad m => t (m a) -> m (t a)

Traversable [] 정의instance Traversable [] where

-- sequenceA :: Applicative f => [f a] -> f [a]

sequenceA [] = pure []

sequenceA (u:us) = (:) <$> u <*> sequenceA us

// or

instance Traversable [] where

sequenceA us =

foldr (\u v -> (:) <$> u <*> v) (pure []) us

Foldable vs Traversable

• Foldable

• Monoid 콘텍스트• fold

• foldMap

• Traversable

• Applicative 콘텍스트• sequenceA

• traverse

Traversable 예제> let rejectWithNegatives = sequenceA . fmap deleteIfNegative

> :t rejectWithNegatives

rejectWithNegatives

:: (Num a, Ord a, Traversable t) => t a -> Maybe (t a)

> rejectWithNegatives testList

Nothing

> rejectWithNegatives [0..10]

Just [0,1,2,3,4,5,6,7,8,9,10]

traverse 를 이용한 Traversable [] 정의

instance Traversable [] where

traverse _ [] = pure []

traverse f (x:xs) = (:) <$> f x <*> traverse f xs

-- Or, equivalently:

instance Traversable [] where

traverse f xs =

foldr (\x v -> (:) <$> f x <*> v) (pure []) xs

traverse 와 sequenceA

traverse :: (Traversable t, Applicative f) => (a -> f b) -> t a -> f (t b)

traverse f xs = sequenceA $ fmap f xs

sequenceA :: (Traversable t, Applicative f) => t (f a) -> f (t a)

sequenceA xs = traverse id xs

Foldable/Traversable

출처 : https://wiki.haskell.org/Foldable_and_Traversable

참고 자료1. CS252 – Advanced Programming Language

Principles Applicative Functors

• http://cs.sjsu.edu/~austin/cs252-fall14/slides/CS252-Day09-ApplicativeFunctors.pdf

2. Haskell/Foldable

• https://en.wikibooks.org/wiki/Haskell/Foldable

3. Haskell/Traversable

• https://en.wikibooks.org/wiki/Haskell/Traversable