Функциональное программирование, весна 2016:...
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[(),(),(),(),()]