O slideshow foi denunciado.
Utilizamos seu perfil e dados de atividades no LinkedIn para personalizar e exibir anúncios mais relevantes. Altere suas preferências de anúncios quando desejar.
Extensible Eff Applicative
@halcat0x15a
今日話すこと
● 背景
○ Applicative
○ Free Applicative
● Free Applicativeの応用
○ Exception Applicative: エラー付きの計算
○ IO(Async) Applicati...
Applicativeとは
FunctorとMonadの中間にある型クラス
(<*>) はコンテナの中の関数をコンテナの中の値に
適用するような関数
class Functor f => Applicative f where
pure :: ...
Applicativeとは
(<*>) は複数のコンテナを合成できる
以下はEither Applicativeの例
e1 :: Either String Integer
e1 = (+) <$> (Right 1) <*> (Right 2...
Free Applicativeとは
Applicativeをデータ型として表したもの
data FreeAp f a where
Pure :: a -> FreeAp f a
ImpureAp :: f a -> FreeAp f (a -...
Free Applicativeとは
FreeApはApplicativeのインスタンス
instance Applicative (FreeAp f) where
pure = Pure
Pure f <*> y = fmap f y
Imp...
Free Applicativeとは
Free Monadのように様々なApplicativeを表現できる
以下はFreeApによるEither Applicativeの表現
newtype Exc e a = Exc e
success ::...
Free Applicativeとは
e1, e2と同等の計算を記述できる
e3 :: FreeAp (Exc String) Integer
e3 = (+) <$> (success 1) <*> (success 2)
e4 :: Fre...
なぜFree Applicativeか
基本的にApplicativeでできることはMonadでできる
applicativeStyle = f <$> ma <*> mb
monadicStyle = do
a <- ma
b <- mb
r...
なぜFree Applicativeか
しかしApplicativeにしかできないこともある
ここではFreer Monadとデータ構造の比較を行う
Freer Monadとは
Monadをデータ型として表したもの
data Freer f a where
Pure :: a -> Freer f a
Impure :: f a -> (a -> Freer f b) -> Freer f ...
Freerとの比較
FreeApとFreerのデータ構造を比較する
e5 :: FreeAp (Exc String) Integer
e5 = ImpureAp (Exc "foo") $ ImpureAp (Exc "bar") $ Pur...
Freerとの比較
Applicativeの式は”foo”と”bar”両方を参照できる
Monadの式は”foo”だけ参照できる
“bar”の取得には継続を実行する必要がある
ImpureAp :: f a -> FreeAp f (a -> ...
Free Applicativeの応用
エラーの収集ができる
runExc :: FreeAp (Exc e) a -> Either [e] a
runExc (Pure a) = Right a
runExc (ImpureAp (Exc ...
Free Applicativeの応用
平行計算ができる
runAsync :: FreeAp IO a -> IO a
runAsync (Pure a) = pure a
runAsync (ImpureAp x k) =
do
a <- ...
Free Applicativeの応用
runAsyncは次のような関数で動作を確認できる
delay1s :: FreeAp IO ()
delay1s = ImpureAp x (Pure id)
where
x = do
putStrLn...
Free Applicativeの応用
非同期で動作しているように見える
> runAsync $ delay1s *> delay1s
starstt
art
end
end
Extensible Eff Applicative
ここまででApplicativeの有用性を示した
ここから拡張可能なFree Applicativeについて考える
Extensible Eff Applicative
Extensible EffectsはFreer MonadにOpen Unionを加えたもの
Free ApplicativeにOpen Unionを加える →
Extensible Ef...
Extensible Eff Applicative
定義はFree Applicativeとそこまで変わらない
data EffAp r a where
Pure :: a -> EffAp r a
ImpureAp :: Union r a...
Extensible Eff Applicative
重要なのは他の作用を跨いだhandlerを書けるかどうか
runExc :: EffAp (Exc e : r) a -> EffAp r (Either [e] a)
runExc (Pu...
Extensible Eff Applicative
IOは終端で処理するしかない
runAsync :: EffAp '[IO] a -> IO a
runAsync (Pure a) = pure a
runAsync (ImpureAp ...
Extensible Eff Applicative
エラー付き計算と非同期計算を組み合わせることができる
handle :: EffAp '[Exc String, IO] a -> IO (Either [String] a)
handle...
Extensible Eff Applicative
> handle e7 >>= print
start
start
enedn
d
Right 3
> handle e8 >>= print
starstt
art
enend
d
Lef...
Extensible Eff Applicative
拡張可能なFree Applicativeを示すことができた
effect handlers
ここで一般化されたハンドラについて考える
以下はEffの例
handle_relay :: (a -> Eff r w) ->
(forall v. t v -> (v -> Eff r w) -> Eff r ...
effect handlers
あまりイケてないがそれっぽいものは書ける
handle_relay :: Functor f =>
(forall a. a -> EffAp r (f a)) ->
(forall a b. t a -> Ef...
effect handlers
ReaderとWriterの例
runReader :: i -> EffAp (Reader i : r) a -> EffAp r a
runReader i = coerce . handle_relay
...
Effとの組み合わせ
Effと相互に利用するにはどうするか
少なくともMonadとApplicativeでprimitiveを分けたくない
Effとの組み合わせ(変換)
EffAp -> Effへの変換を提供する
toEff :: EffAp r a -> Eff.Eff r a
toEff (Pure a) = Eff.Pure a
toEff (ImpureAp u k) = ...
Effとの組み合わせ(変換)
● Pros
○ Monadの操作とApplicativeの操作で型が分かれる
● Cons
○ モナドを利用したい時に変換しなければならない
Effとの組み合わせ(コンストラクタ)
コンストラクタに含める
data Eff r a where
Pure :: a -> Eff r a
Impure :: Union r a -> (a -> Eff r b) -> Eff r b
I...
Effとの組み合わせ(コンストラクタ)
関数のところを抽象化してもよい
data Eff r a where
Pure :: a -> Eff r a
Impure :: Union r a -> Arr r a b -> Eff r b
da...
Effとの組み合わせ(コンストラクタ)
● Pros
○ 使いやすい
● Cons
○ Applicativeの操作を型で保証できない
Effとの組み合わせ(型パラメータ)
型パラメータを増やす
data Eff h r a where
Pure :: a -> Eff h r a
Impure :: Union r a -> h (Eff h r) a b -> Eff h ...
Effとの組み合わせ(型パラメータ)
MonadとApplicativeで共通のprimitiveを使える
send :: (FromApply h, Member f r) => f a -> Eff h r a
send fa = Impu...
Effとの組み合わせ(型パラメータ)
● Pros
○ コンストラクタが共通
○ 型が分かれる
● Cons
○ 型が複雑になる
まとめ
● Applicativeにできて、Monadにできないことがある
● extensibleなFree Applicativeが作れる
● Eff MonadにFree Applicativeを組み込めるかもしれない
みなさんへの課題
● 簡潔なハンドラの定義
● データ構造をどうするか
参考文献
● http://okmij.org/ftp/Haskell/extensible/more.pdf
● https://www.slideshare.net/konn/freer-monads-more-exten
sible-ef...
おわり
Próximos SlideShares
Carregando em…5
×

Extensible Eff Applicative

557 visualizações

Publicada em

https://connpass.com/event/124786/

Publicada em: Engenharia
  • Seja o primeiro a comentar

Extensible Eff Applicative

  1. 1. Extensible Eff Applicative @halcat0x15a
  2. 2. 今日話すこと ● 背景 ○ Applicative ○ Free Applicative ● Free Applicativeの応用 ○ Exception Applicative: エラー付きの計算 ○ IO(Async) Applicative: 非同期の計算 ● Extensible Eff Applicative: 拡張可能なFreeAp ● Eff Monadとの組み合わせ
  3. 3. Applicativeとは FunctorとMonadの中間にある型クラス (<*>) はコンテナの中の関数をコンテナの中の値に 適用するような関数 class Functor f => Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b
  4. 4. Applicativeとは (<*>) は複数のコンテナを合成できる 以下はEither Applicativeの例 e1 :: Either String Integer e1 = (+) <$> (Right 1) <*> (Right 2) e2 :: Either String Integer e2 = (+) <$> (Right 1) <*> (Left "hoge")
  5. 5. Free Applicativeとは Applicativeをデータ型として表したもの data FreeAp f a where Pure :: a -> FreeAp f a ImpureAp :: f a -> FreeAp f (a -> b) -> FreeAp f b class Applicative f where pure :: a -> f a (<*>) :: f (a -> b) -> f a -> f b
  6. 6. Free Applicativeとは FreeApはApplicativeのインスタンス instance Applicative (FreeAp f) where pure = Pure Pure f <*> y = fmap f y ImpureAp x y <*> z = ImpureAp x (flip <$> y <*> z)
  7. 7. Free Applicativeとは Free Monadのように様々なApplicativeを表現できる 以下はFreeApによるEither Applicativeの表現 newtype Exc e a = Exc e success :: a -> FreeAp (Exc e) a success a = Pure a failure :: e -> FreeAp (Exc e) a failure e = ImpureAp (Exc e) (Pure id)
  8. 8. Free Applicativeとは e1, e2と同等の計算を記述できる e3 :: FreeAp (Exc String) Integer e3 = (+) <$> (success 1) <*> (success 2) e4 :: FreeAp (Exc String) Integer e4 = (+) <$> (success 1) <*> (failure "hoge")
  9. 9. なぜFree Applicativeか 基本的にApplicativeでできることはMonadでできる applicativeStyle = f <$> ma <*> mb monadicStyle = do a <- ma b <- mb return $ f a b
  10. 10. なぜFree Applicativeか しかしApplicativeにしかできないこともある ここではFreer Monadとデータ構造の比較を行う
  11. 11. Freer Monadとは Monadをデータ型として表したもの data Freer f a where Pure :: a -> Freer f a Impure :: f a -> (a -> Freer f b) -> Freer f b class Monad m where return :: a -> m a (>>=) :: m a -> (a -> m b) -> m b
  12. 12. Freerとの比較 FreeApとFreerのデータ構造を比較する e5 :: FreeAp (Exc String) Integer e5 = ImpureAp (Exc "foo") $ ImpureAp (Exc "bar") $ Pure (+) e6 :: Freer (Exc String) Integer e6 = Impure (Exc "foo") $ a -> Impure (Exc "bar") $ b -> Pure (a + b)
  13. 13. Freerとの比較 Applicativeの式は”foo”と”bar”両方を参照できる Monadの式は”foo”だけ参照できる “bar”の取得には継続を実行する必要がある ImpureAp :: f a -> FreeAp f (a -> b) -> FreeAp f b Impure :: f a -> (a -> Freer f b) -> Freer f b
  14. 14. Free Applicativeの応用 エラーの収集ができる runExc :: FreeAp (Exc e) a -> Either [e] a runExc (Pure a) = Right a runExc (ImpureAp (Exc e) k) = case runExc k of Right _ -> Left [e] Left es -> Left (e : es) > runExc e5 Left ["foo","bar"]
  15. 15. Free Applicativeの応用 平行計算ができる runAsync :: FreeAp IO a -> IO a runAsync (Pure a) = pure a runAsync (ImpureAp x k) = do a <- async x k' <- runAsync k x' <- wait a return $ k' x'
  16. 16. Free Applicativeの応用 runAsyncは次のような関数で動作を確認できる delay1s :: FreeAp IO () delay1s = ImpureAp x (Pure id) where x = do putStrLn "start" threadDelay 1000000 putStrLn "end"
  17. 17. Free Applicativeの応用 非同期で動作しているように見える > runAsync $ delay1s *> delay1s starstt art end end
  18. 18. Extensible Eff Applicative ここまででApplicativeの有用性を示した ここから拡張可能なFree Applicativeについて考える
  19. 19. Extensible Eff Applicative Extensible EffectsはFreer MonadにOpen Unionを加えたもの Free ApplicativeにOpen Unionを加える → Extensible Eff Applicative!
  20. 20. Extensible Eff Applicative 定義はFree Applicativeとそこまで変わらない data EffAp r a where Pure :: a -> EffAp r a ImpureAp :: Union r a -> EffAp r (a -> b) -> EffAp r b
  21. 21. Extensible Eff Applicative 重要なのは他の作用を跨いだhandlerを書けるかどうか runExc :: EffAp (Exc e : r) a -> EffAp r (Either [e] a) runExc (Pure a) = Pure $ Right a runExc (ImpureAp u k) = case decomp u of Right (Exc e) -> fmap f (runExc k) where f (Right _) = Left [e] f (Left es) = Left (e : es) Left u -> ImpureAp u $ fmap f (runExc k) where f e a = fmap (k -> k a) e
  22. 22. Extensible Eff Applicative IOは終端で処理するしかない runAsync :: EffAp '[IO] a -> IO a runAsync (Pure a) = pure a runAsync (ImpureAp u k) = do let Right x = decomp u a <- async x k' <- runAsync k x' <- wait a return $ k' x'
  23. 23. Extensible Eff Applicative エラー付き計算と非同期計算を組み合わせることができる handle :: EffAp '[Exc String, IO] a -> IO (Either [String] a) handle = runAsync . runExc e7 :: (Member (Exc String) r, Member IO r) => EffAp r Integer e7 = (+) <$> (delay1s *> success 1) <*> (success 2 <* delay1s) e8 :: (Member (Exc String) r, Member IO r) => EffAp r Integer e8 = (+) <$> (delay1s *> failure "foo") <*> (failure "bar" <* delay1s)
  24. 24. Extensible Eff Applicative > handle e7 >>= print start start enedn d Right 3 > handle e8 >>= print starstt art enend d Left ["foo","bar"]
  25. 25. Extensible Eff Applicative 拡張可能なFree Applicativeを示すことができた
  26. 26. effect handlers ここで一般化されたハンドラについて考える 以下はEffの例 handle_relay :: (a -> Eff r w) -> (forall v. t v -> (v -> Eff r w) -> Eff r w) -> Eff (t : r ) a -> Eff r w handle_relay ret _ (Pure x) = ret x handle_relay ret h (Impure u q) = case decomp u of Right x -> h x k Left u -> Impure u k where k = handle_relay ret h . q
  27. 27. effect handlers あまりイケてないがそれっぽいものは書ける handle_relay :: Functor f => (forall a. a -> EffAp r (f a)) -> (forall a b. t a -> EffAp r (f (a -> b)) -> EffAp r (f b)) -> EffAp (t : r ) a -> EffAp r (f a) handle_relay ret _ (Pure x) = ret x handle_relay ret h (ImpureAp u q) = case decomp u of Right x -> h x k Left u -> ImpureAp u (fmap f k) where k = handle_relay ret h q f x a = fmap (k -> k a) x
  28. 28. effect handlers ReaderとWriterの例 runReader :: i -> EffAp (Reader i : r) a -> EffAp r a runReader i = coerce . handle_relay (Pure . Identity) (Ask -> fmap ((Identity k) -> Identity $ k i)) runWriter :: Monoid w => EffAp (Writer w : r) a -> EffAp r (w, a) runWriter = handle_relay (a -> Pure (mempty, a)) ((Tell v) -> fmap ((w, k) -> (mappend v w, k ())))
  29. 29. Effとの組み合わせ Effと相互に利用するにはどうするか 少なくともMonadとApplicativeでprimitiveを分けたくない
  30. 30. Effとの組み合わせ(変換) EffAp -> Effへの変換を提供する toEff :: EffAp r a -> Eff.Eff r a toEff (Pure a) = Eff.Pure a toEff (ImpureAp u k) = Eff.Impure u (a -> fmap (k -> k a) (toEff k))
  31. 31. Effとの組み合わせ(変換) ● Pros ○ Monadの操作とApplicativeの操作で型が分かれる ● Cons ○ モナドを利用したい時に変換しなければならない
  32. 32. Effとの組み合わせ(コンストラクタ) コンストラクタに含める data Eff r a where Pure :: a -> Eff r a Impure :: Union r a -> (a -> Eff r b) -> Eff r b ImpureAp :: Union r a -> Eff r (a -> b) -> Eff r b
  33. 33. Effとの組み合わせ(コンストラクタ) 関数のところを抽象化してもよい data Eff r a where Pure :: a -> Eff r a Impure :: Union r a -> Arr r a b -> Eff r b data Arr r a b = ArrA (Eff r (a -> b)) | ArrM (a -> Eff r b)
  34. 34. Effとの組み合わせ(コンストラクタ) ● Pros ○ 使いやすい ● Cons ○ Applicativeの操作を型で保証できない
  35. 35. Effとの組み合わせ(型パラメータ) 型パラメータを増やす data Eff h r a where Pure :: a -> Eff h r a Impure :: Union r a -> h (Eff h r) a b -> Eff h r b data Apply f a b where Apply :: f (a -> b) -> Apply f a b data Bind f a b where Bind :: (a -> f b) -> Bind f a b
  36. 36. Effとの組み合わせ(型パラメータ) MonadとApplicativeで共通のprimitiveを使える send :: (FromApply h, Member f r) => f a -> Eff h r a send fa = Impure (inj fa) (fromApply $ Apply $ Pure id) class FromApply h where fromApply :: Functor f => Apply f a b -> h f a b
  37. 37. Effとの組み合わせ(型パラメータ) ● Pros ○ コンストラクタが共通 ○ 型が分かれる ● Cons ○ 型が複雑になる
  38. 38. まとめ ● Applicativeにできて、Monadにできないことがある ● extensibleなFree Applicativeが作れる ● Eff MonadにFree Applicativeを組み込めるかもしれない
  39. 39. みなさんへの課題 ● 簡潔なハンドラの定義 ● データ構造をどうするか
  40. 40. 参考文献 ● http://okmij.org/ftp/Haskell/extensible/more.pdf ● https://www.slideshare.net/konn/freer-monads-more-exten sible-effects-59411772 ● https://arxiv.org/abs/1403.0749 ● http://oleg.fi/gists/posts/2018-02-21-single-free.html
  41. 41. おわり

×