“Нам для сертификации надо чтобы каждая функция логировала свой вызов.”
Неудобно программировать
f :: () -> a
эквивалентно f :: a
Потому что у ()
всего одно значение (()
), а любая функция для одинаковых аргументов всегда возвращает одинаковые значения (потому что по-другому невозможно).
return
– нейтральный элемент по >=>
type Markup = Int
getCoffee :: Markup -> Order -> Coffee
payForCoffee :: Markup -> Coffee -> Payment
buyCoffee :: Markup -> Order -> Payment
buyCoffee markup = payForCoffee markup . getCoffee markup
r
– то, что у нас в “окружении”.
type Price = Int
getCoffeePrice :: Markup -> Coffee -> Price
getDiscount :: Markup -> Coffee -> Price
getPayment :: Markup -> Price -> Payment
payForCoffee :: Markup -> Coffee -> Payment
payForCoffee markup coffee = getPayment markup amount
where
coffeePrice = getCoffeePrice markup coffee
discount = getDiscount markup coffee
amount = coffeePrice - discount
type PricingEnv = Reader Markup
getCoffeePrice :: Coffee -> PricingEnv Price
getDiscount :: Coffee -> PricingEnv Price
getPayment :: Price -> PricingEnv Payment
payForCoffee :: Coffee -> PricingEnv Payment
payForCoffee coffee =
coffee >>= getCoffeePrice >>= \coffeePrice ->
coffee >>= getDiscount >>= \discount ->
getPayment (coffeePrice - discount)
type PricingEnv = Reader Markup
getCoffeePrice :: Coffee -> PricingEnv Price
getDiscount :: Coffee -> PricingEnv Price
getPayment :: Price -> PricingEnv Payment
payForCoffee :: Coffee -> PricingEnv Payment
payForCoffee coffee =
coffee >>= getCoffeePrice >>= \coffeePrice ->
coffee >>= getDiscount >>= \discount ->
getPayment (coffeePrice - discount)
Откуда брать orderId
?
createOrder :: Coffee -> Reader Int Order
createOrder coffee = do
newId <- ask
return (Order coffee newId)
🎉
Все id
будут одинаковые.
Reader
эквивалентно глобальной константе.
Айдишники – скорее глобальная переменная.
– Но у нас же нет переменных!
– Да, нет!
– Это какой-то процедурный языке получается!
– Лучше!*
class Monad [] where
return x = [x]
(>>=) :: [a] -> (a -> [b]) -> [b]
[] >>= _ = []
(a : aa) >>= f = f a <> (a >>= f)
Контекст недетерменированности (нескольких вариантов)
Тривиальная монада
Монада – перегрузка композиции функций.
Аппликативный функтор – перегрузка применения функций.
– Почему не (a -> b) -> f a -> f b
.
– Это fmap
. (И функции нескольких аргументов)