SlideShare une entreprise Scribd logo
1  sur  41
Télécharger pour lire hors ligne
Extensible Eff Applicative
@halcat0x15a
今日話すこと
● 背景
○ Applicative
○ Free Applicative
● Free Applicativeの応用
○ Exception Applicative: エラー付きの計算
○ IO(Async) Applicative: 非同期の計算
● Extensible Eff Applicative: 拡張可能なFreeAp
● Eff Monadとの組み合わせ
Applicativeとは
FunctorとMonadの中間にある型クラス
(<*>) はコンテナの中の関数をコンテナの中の値に
適用するような関数
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
Applicativeとは
(<*>) は複数のコンテナを合成できる
以下はEither Applicativeの例
e1 :: Either String Integer
e1 = (+) <$> (Right 1) <*> (Right 2)
e2 :: Either String Integer
e2 = (+) <$> (Right 1) <*> (Left "hoge")
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
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)
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)
Free Applicativeとは
e1, e2と同等の計算を記述できる
e3 :: FreeAp (Exc String) Integer
e3 = (+) <$> (success 1) <*> (success 2)
e4 :: FreeAp (Exc String) Integer
e4 = (+) <$> (success 1) <*> (failure "hoge")
なぜFree Applicativeか
基本的にApplicativeでできることはMonadでできる
applicativeStyle = f <$> ma <*> mb
monadicStyle = do
a <- ma
b <- mb
return $ f a b
なぜ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 b
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
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)
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
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"]
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'
Free Applicativeの応用
runAsyncは次のような関数で動作を確認できる
delay1s :: FreeAp IO ()
delay1s = ImpureAp x (Pure id)
where
x = do
putStrLn "start"
threadDelay 1000000
putStrLn "end"
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 Eff Applicative!
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
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
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'
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)
Extensible Eff Applicative
> handle e7 >>= print
start
start
enedn
d
Right 3
> handle e8 >>= print
starstt
art
enend
d
Left ["foo","bar"]
Extensible Eff Applicative
拡張可能なFree Applicativeを示すことができた
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
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
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 ())))
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.Impure u (a -> fmap (k -> k a)
(toEff 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
ImpureAp :: Union r a -> Eff r (a -> b) -> Eff r b
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)
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 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
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
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-effects-59411772
● https://arxiv.org/abs/1403.0749
● http://oleg.fi/gists/posts/2018-02-21-single-free.html
おわり

Contenu connexe

Tendances

Howto CAD and Meshing on DEXCS2021
Howto CAD and Meshing on DEXCS2021Howto CAD and Meshing on DEXCS2021
Howto CAD and Meshing on DEXCS2021Etsuji Nomura
 
言語の設計判断
言語の設計判断言語の設計判断
言語の設計判断nishio
 
Prefixから始めるgentoo生活
Prefixから始めるgentoo生活Prefixから始めるgentoo生活
Prefixから始めるgentoo生活bontakun
 
SharePoint Online を JavaScript でイジる。
SharePoint Online を JavaScript でイジる。SharePoint Online を JavaScript でイジる。
SharePoint Online を JavaScript でイジる。Hirofumi Ota
 
圏論のモナドとHaskellのモナド
圏論のモナドとHaskellのモナド圏論のモナドとHaskellのモナド
圏論のモナドとHaskellのモナドYoshihiro Mizoguchi
 
サーバサイドの並行プログラミング〜かんたんマルチスレッドプログラミング〜
サーバサイドの並行プログラミング〜かんたんマルチスレッドプログラミング〜サーバサイドの並行プログラミング〜かんたんマルチスレッドプログラミング〜
サーバサイドの並行プログラミング〜かんたんマルチスレッドプログラミング〜gree_tech
 
Zabbixで学ぶ統計解析入門
Zabbixで学ぶ統計解析入門Zabbixで学ぶ統計解析入門
Zabbixで学ぶ統計解析入門Takeo Noda
 
遺伝子のアノテーション付加
遺伝子のアノテーション付加遺伝子のアノテーション付加
遺伝子のアノテーション付加弘毅 露崎
 
ParaviewでのParticle Tracerを用いた可視化
ParaviewでのParticle Tracerを用いた可視化ParaviewでのParticle Tracerを用いた可視化
ParaviewでのParticle Tracerを用いた可視化takuyayamamoto1800
 
Using PyFoam as library(第25回オープンCAE勉強会@関西)
Using PyFoam as library(第25回オープンCAE勉強会@関西)Using PyFoam as library(第25回オープンCAE勉強会@関西)
Using PyFoam as library(第25回オープンCAE勉強会@関西)TatsuyaKatayama
 
猫でも分かりたい線形回帰の自由度
猫でも分かりたい線形回帰の自由度猫でも分かりたい線形回帰の自由度
猫でも分かりたい線形回帰の自由度YukinoriKambe
 
純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門Kimikazu Kato
 
Rでのtry関数によるエラー処理
Rでのtry関数によるエラー処理Rでのtry関数によるエラー処理
Rでのtry関数によるエラー処理wada, kazumi
 
今から始める Lens/Prism
今から始める Lens/Prism今から始める Lens/Prism
今から始める Lens/PrismNaoki Aoyama
 
Extensible Effects in Dotty
Extensible Effects in DottyExtensible Effects in Dotty
Extensible Effects in DottySanshiro Yoshida
 
深層ガウス過程とアクセントの潜在変数表現に基づく音声合成の検討
深層ガウス過程とアクセントの潜在変数表現に基づく音声合成の検討深層ガウス過程とアクセントの潜在変数表現に基づく音声合成の検討
深層ガウス過程とアクセントの潜在変数表現に基づく音声合成の検討Tomoki Koriyama
 
Proof summit 2017 for slideshare
Proof summit 2017 for slideshareProof summit 2017 for slideshare
Proof summit 2017 for slideshareKeisuke Yahata
 
よくわかるCoqプログラミング
よくわかるCoqプログラミングよくわかるCoqプログラミング
よくわかるCoqプログラミングReal_analysis
 
相互情報量を用いた独立性の検定
相互情報量を用いた独立性の検定相互情報量を用いた独立性の検定
相互情報量を用いた独立性の検定Joe Suzuki
 

Tendances (20)

Howto CAD and Meshing on DEXCS2021
Howto CAD and Meshing on DEXCS2021Howto CAD and Meshing on DEXCS2021
Howto CAD and Meshing on DEXCS2021
 
C++の黒魔術
C++の黒魔術C++の黒魔術
C++の黒魔術
 
言語の設計判断
言語の設計判断言語の設計判断
言語の設計判断
 
Prefixから始めるgentoo生活
Prefixから始めるgentoo生活Prefixから始めるgentoo生活
Prefixから始めるgentoo生活
 
SharePoint Online を JavaScript でイジる。
SharePoint Online を JavaScript でイジる。SharePoint Online を JavaScript でイジる。
SharePoint Online を JavaScript でイジる。
 
圏論のモナドとHaskellのモナド
圏論のモナドとHaskellのモナド圏論のモナドとHaskellのモナド
圏論のモナドとHaskellのモナド
 
サーバサイドの並行プログラミング〜かんたんマルチスレッドプログラミング〜
サーバサイドの並行プログラミング〜かんたんマルチスレッドプログラミング〜サーバサイドの並行プログラミング〜かんたんマルチスレッドプログラミング〜
サーバサイドの並行プログラミング〜かんたんマルチスレッドプログラミング〜
 
Zabbixで学ぶ統計解析入門
Zabbixで学ぶ統計解析入門Zabbixで学ぶ統計解析入門
Zabbixで学ぶ統計解析入門
 
遺伝子のアノテーション付加
遺伝子のアノテーション付加遺伝子のアノテーション付加
遺伝子のアノテーション付加
 
ParaviewでのParticle Tracerを用いた可視化
ParaviewでのParticle Tracerを用いた可視化ParaviewでのParticle Tracerを用いた可視化
ParaviewでのParticle Tracerを用いた可視化
 
Using PyFoam as library(第25回オープンCAE勉強会@関西)
Using PyFoam as library(第25回オープンCAE勉強会@関西)Using PyFoam as library(第25回オープンCAE勉強会@関西)
Using PyFoam as library(第25回オープンCAE勉強会@関西)
 
猫でも分かりたい線形回帰の自由度
猫でも分かりたい線形回帰の自由度猫でも分かりたい線形回帰の自由度
猫でも分かりたい線形回帰の自由度
 
純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門
 
Rでのtry関数によるエラー処理
Rでのtry関数によるエラー処理Rでのtry関数によるエラー処理
Rでのtry関数によるエラー処理
 
今から始める Lens/Prism
今から始める Lens/Prism今から始める Lens/Prism
今から始める Lens/Prism
 
Extensible Effects in Dotty
Extensible Effects in DottyExtensible Effects in Dotty
Extensible Effects in Dotty
 
深層ガウス過程とアクセントの潜在変数表現に基づく音声合成の検討
深層ガウス過程とアクセントの潜在変数表現に基づく音声合成の検討深層ガウス過程とアクセントの潜在変数表現に基づく音声合成の検討
深層ガウス過程とアクセントの潜在変数表現に基づく音声合成の検討
 
Proof summit 2017 for slideshare
Proof summit 2017 for slideshareProof summit 2017 for slideshare
Proof summit 2017 for slideshare
 
よくわかるCoqプログラミング
よくわかるCoqプログラミングよくわかるCoqプログラミング
よくわかるCoqプログラミング
 
相互情報量を用いた独立性の検定
相互情報量を用いた独立性の検定相互情報量を用いた独立性の検定
相互情報量を用いた独立性の検定
 

Similaire à Extensible Eff Applicative

すごいHaskell 第7章 型や型クラスを自分で作ろう(後編)
すごいHaskell 第7章 型や型クラスを自分で作ろう(後編)すごいHaskell 第7章 型や型クラスを自分で作ろう(後編)
すごいHaskell 第7章 型や型クラスを自分で作ろう(後編)Nozomu Kaneko
 
すごいHaskell読書会#10
すごいHaskell読書会#10すごいHaskell読書会#10
すごいHaskell読書会#10Shin Ise
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料時響 逢坂
 
モナドがいっぱい!
モナドがいっぱい!モナドがいっぱい!
モナドがいっぱい!Kenta Sato
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料時響 逢坂
 
Fork/Join Framework。そしてLambdaへ。
Fork/Join Framework。そしてLambdaへ。Fork/Join Framework。そしてLambdaへ。
Fork/Join Framework。そしてLambdaへ。Yuichi Sakuraba
 
F#とC#で見る関数志向プログラミング
F#とC#で見る関数志向プログラミングF#とC#で見る関数志向プログラミング
F#とC#で見る関数志向プログラミングsatoshimurakumo
 
Swift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsap
Swift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsapSwift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsap
Swift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsapTomohiro Kumagai
 

Similaire à Extensible Eff Applicative (10)

Applicative functor
Applicative functorApplicative functor
Applicative functor
 
すごいHaskell 第7章 型や型クラスを自分で作ろう(後編)
すごいHaskell 第7章 型や型クラスを自分で作ろう(後編)すごいHaskell 第7章 型や型クラスを自分で作ろう(後編)
すごいHaskell 第7章 型や型クラスを自分で作ろう(後編)
 
すごいHaskell読書会#10
すごいHaskell読書会#10すごいHaskell読書会#10
すごいHaskell読書会#10
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料
 
モナドがいっぱい!
モナドがいっぱい!モナドがいっぱい!
モナドがいっぱい!
 
Ekmett勉強会発表資料
Ekmett勉強会発表資料Ekmett勉強会発表資料
Ekmett勉強会発表資料
 
Fork/Join Framework。そしてLambdaへ。
Fork/Join Framework。そしてLambdaへ。Fork/Join Framework。そしてLambdaへ。
Fork/Join Framework。そしてLambdaへ。
 
F#とC#で見る関数志向プログラミング
F#とC#で見る関数志向プログラミングF#とC#で見る関数志向プログラミング
F#とC#で見る関数志向プログラミング
 
Swift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsap
Swift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsapSwift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsap
Swift 3.0 の新機能 - 追加・変更まわりだけ、ざっくり紹介 2 #devsap
 
Swiftおさらい
SwiftおさらいSwiftおさらい
Swiftおさらい
 

Extensible Eff Applicative