Функциональное программирование, весна 2016:...

Download Функциональное программирование, весна 2016: Использование монад

If you can't read please download the document

Upload: cs-center

Post on 24-Jan-2017

283 views

Category:

Documents


0 download

TRANSCRIPT

  • 10.

    , CSC

    12.04.2016

  • 1 Reader:

    2 Writer:

    3 State:

    4 IO: -

  • 1 Reader:

    2 Writer:

    3 State:

    4 IO: -

  • Reader (Environment)

    , .

    instance Monad ((->) r) wherereturn :: a -> (r -> a)return x = \_ -> x

    (>>=) :: (r -> a) -> (a -> (r -> b)) -> (r -> b)m >>= k = \e -> k (m e) e

    return ;(>>=) .

  • Reader

    newtype Reader r a = Reader { runReader :: (r -> a) }

    Reader r a -, :

    reader :: (r -> a) -> Reader r arunReader :: Reader r a -> r -> a

    instance Monad (Reader r) wherereturn x = reader $ \e -> xm >>= k = reader $ \e -> let v = runReader m e

    in runReader (k v) e

  • Reader

    Reader, Int

    simpleReader :: Reader Int StringsimpleReader = reader (\e -> "Environment is " ++ show e)

    *Fp10> runReader simpleReader 42"Environment is 42"

  • ask

    ask :: Reader r r

    type User = Stringtype Password = Stringtype UsersTable = [(User,Password)]

    pwds :: UsersTablepwds = [("Bill","123"),("Ann","qwerty"),("John","2sRq8P")]

    firstUser :: Reader UsersTable UserfirstUser = do

    e runReader firstUser pwds"Bill"

  • asks

    asks :: (r -> a) -> Reader r a

    getPwdLen :: User -> Reader UsersTable IntgetPwdLen person = do

    mbPwd runReader (getPwdLen "Ann") pwds6*Fp10> runReader (getPwdLen "Ann") []-1

  • local

    local :: (r -> r) -> Reader r a -> Reader r a

    usersCount :: Reader UsersTable IntusersCount = asks length

    localTest :: Reader UsersTable (Int,Int)localTest = do

    count1 runReader localTest [](0,1)

  • MonadReader

    () Reader,

    class Monad m => MonadReader r m | m -> r whereask :: m rlocal :: (r -> r) -> m a -> m areader :: (r -> a) -> m areader f = do

    r IntdoIt = do

    a

  • 1 Reader:

    2 Writer:

    3 State:

    4 IO: -

  • Writer

    , .

    newtype Writer w a = Writer {runWriter :: (a, w)}

    writer :: (a, w) -> Writer w arunWriter :: Writer w a -> (a, w)execWriter :: Writer w a -> w

    Monoid .

    instance (Monoid w) => Monad (Writer w) wherereturn x = writer (x, mempty)m >>= k = let (x,u) = runWriter m

    (y,v) = runWriter $ k xin writer (y, u mappend v)

  • Writer:

    :

    GHCi

    *Fp10> runWriter (return 3 :: Writer String Int)(3,"")*Fp10> runWriter (return 3 :: Writer (Sum Int) Int)(3,Sum {getSum = 0})*Fp10> execWriter (return 3 :: Writer (Product Int) Int)Product {getProduct = 1}

  • Writer:

    - -.

    type Vegetable = String

    type Price = Doubletype Qty = Doubletype Cost = Double

    type PriceList = [(Vegetable,Price)]

    prices :: PriceListprices = [("Potato",13),("Tomato",55),("Apple",48)]

  • tell

    tell :: Monoid w => w -> Writer w ()

    addVegetable :: Vegetable -> Qty-> Writer (Sum Cost) (Vegetable, Price)

    addVegetable veg qty = dolet pr = fromMaybe 0 $ lookup veg priceslet cost = qty * prtell $ Sum costreturn (veg, pr)

    *Fp10> runWriter $ addVegetable "Apple" 100(("Apple",48.0),Sum {getSum = 4800.0})*Fp10> runWriter $ addVegetable "Pear" 100(("Pear",0.0),Sum {getSum = 0.0})

  • addVegetable

    myCart0 = dox1

  • listen

    , listen :: Monoid w => Writer w a -> Writer w (a, w)

    myCart1 = dox1

  • listens

    listens :: Monoid w => (w -> b) -> Writer w a -> Writer w (a, b)

    myCart1 = dox1

  • censor

    censor :: Monoid w => (w -> w) -> Writer w a -> Writer w a

    myCart0 = censor (discount 10) myCart0

    discount proc (Sum x) = Sum $ if x < 100 then xelse x * (100 - proc) / 100

    GHCi

    *Fp10> execWriter myCart0Sum {getSum = 100.5}*Fp10> execWriter myCart0Sum {getSum = 90.45}

  • 1 Reader:

    2 Writer:

    3 State:

    4 IO: -

  • State

    , .

    newtype State s a = State { runState :: s -> (a,s) }

    state :: (s -> (a,s)) -> State s arunState :: State s a -> s -> (a,s)

    instance Monad (State s) wherereturn x = state $ \st -> (x,st)m >>= k = state $ \st -> let (x,st) = runState m st

    m = k xin runState m st

    return , . (>>=) .

  • State:

    , , :

    runState :: State s a -> s -> (a,s)execState :: State s a -> s -> sevalState :: State s a -> s -> a

    GHCi

    *Fp10> runState (return 3 :: State String Int) "Hi, State!"(3,"Hi, State!")*Fp10> execState (return 3 :: State String Int) "Hi, State!""Hi, State!"*Fp10> evalState (return 3 :: State String Int) "Hi, State!"3

  • State:

    get :: State s sget = state $ \s -> (s,s)

    put :: s -> State s ()put s = state $ \_ -> ((),s)

    modify :: (s -> s) -> State s ()modify f = do s a) -> State s agets f = do s

  • State:

    tick :: State Int Inttick = do n runState tick 3(3,4)

    succ :: Int -> Intsucc n = execState tick n

    plus :: Int -> Int -> Intplus n x = execState (sequence $ replicate n tick) x

  • plus :: Int -> Int -> Intplus n x = execState (sequence $ replicate n tick) x

    sequence . replicate n , Control.Monad

    replicateM :: (Monad m) => Int -> m a -> m [a]replicateM n = sequence . replicate n

    plus :: Int -> Int -> Intplus n x = execState (replicateM n tick) x

  • State . ST . STRef.

    runST :: (forall s. ST s a) -> a

    IORef STRef .MVar IORef , .TVar STM(Software transactional memory).

  • 1 Reader:

    2 Writer:

    3 State:

    4 IO: -

  • -

    , , - .

    getCharFromConsole :: Char

    ! ?

    getCharFromConsole :: RealWorld -> (RealWorld, Char)

    RealWorld .

  • -

    , , - .

    getCharFromConsole :: Char

    ! ?

    getCharFromConsole :: RealWorld -> (RealWorld, Char)

    RealWorld .

  • IO

    IO , -. GHC (, (#), )

    newtype IO a = IO (RealWorld -> (RealWorld, a))

    RealWorld deeplymagical, , . , RealWorld ! - main .

  • IO:

    newtype IO a = IO (RealWorld -> (RealWorld, a))

    unIO :: IO a -> RealWorld -> (RealWorld, a)unIO (IO a) = a

    instance Monad IO wherereturn x = IO $ \w -> (w, x)

    (>>=) (IO m) k = IO $\w -> case m w of (new_w, a) -> unIO (k a) new_w

    , :

    . .

  • -

    :

    getChar :: IO ChargetLine :: IO StringgetContents :: IO String

    :

    putChar :: Char -> IO ()putStr, putStrLn :: String -> IO ()print :: Show a => a -> IO ()

    -:

    interact :: (String -> String) -> IO ()

  • -

    main = doputStrLn "What is your name?"name >getLine >>= \name ->putStrLn $ "Nice to meet you, " ++ name ++ "!"

  • -

    main = doputStrLn "What is your name?"name >getLine >>= \name ->putStrLn $ "Nice to meet you, " ++ name ++ "!"

  • getLine

    , getChar, getLine?

    getLine :: IO StringgetLine = do

    c

  • putStr

    , putChar, putStr?

    putStr :: String -> IO ()putStr [] = return ()putStr (x:xs) = putChar x >> putStr xs

    sequence_ :: Monad m => [m a] -> m ()sequence_ = foldr (>>) (return ())

    putStr :: String -> IO ()putStr = sequence_ . map putChar

  • putStr (2)

    putStr :: String -> IO ()putStr = sequence_ . map putChar

    .

    mapM_ :: Monad m => (a -> m b) -> [a] -> m ()mapM_ f = sequence_ . map f

    ,

    putStr :: String -> IO ()putStr = mapM_ putChar

  • sequence_ mapM_

    sequence :: Monad m => [m a] -> m [a]sequence ms = foldr k (return []) ms

    where k :: Monad m => m a -> m [a] -> m [a]k m m = do { x m b) -> [a] -> m [b]mapM f = sequence . map f

    GHCi

    *Fp10> mapM_ putChar "Hello"Hello*Fp10> mapM putChar "Hello"Hello[(),(),(),(),()]