SlideShare ist ein Scribd-Unternehmen logo
1 von 41
Downloaden Sie, um offline zu lesen
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
おわり

Weitere ähnliche Inhalte

Was ist angesagt?

traitを使って楽したい話
traitを使って楽したい話traitを使って楽したい話
traitを使って楽したい話infinite_loop
 
Extensible Effects in Dotty
Extensible Effects in DottyExtensible Effects in Dotty
Extensible Effects in DottySanshiro Yoshida
 
関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐり関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐりKazuyuki TAKASE
 
純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門Kimikazu Kato
 
Capabilities for Resources and Effects
Capabilities for Resources and EffectsCapabilities for Resources and Effects
Capabilities for Resources and EffectsMartin Odersky
 
ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2
ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2
ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2Masatoshi Tada
 
最適化計算/パラメータスタディーとFreeCADの連携についての調査
最適化計算/パラメータスタディーとFreeCADの連携についての調査最適化計算/パラメータスタディーとFreeCADの連携についての調査
最適化計算/パラメータスタディーとFreeCADの連携についての調査Daisuke Matsubara
 
Boundary Conditions in OpenFOAM
Boundary Conditions in OpenFOAMBoundary Conditions in OpenFOAM
Boundary Conditions in OpenFOAMFumiya Nozaki
 
OpenFOAM の境界条件をまとめよう!
OpenFOAM の境界条件をまとめよう!OpenFOAM の境界条件をまとめよう!
OpenFOAM の境界条件をまとめよう!Fumiya Nozaki
 
デザインパターン(初歩的な7パターン)
デザインパターン(初歩的な7パターン)デザインパターン(初歩的な7パターン)
デザインパターン(初歩的な7パターン)和明 斎藤
 
Jbatch実践入門 #jdt2015
Jbatch実践入門 #jdt2015Jbatch実践入門 #jdt2015
Jbatch実践入門 #jdt2015Norito Agetsuma
 
Scala 初心者が米田の補題を Scala で考えてみた
Scala 初心者が米田の補題を Scala で考えてみたScala 初心者が米田の補題を Scala で考えてみた
Scala 初心者が米田の補題を Scala で考えてみたKazuyuki TAKASE
 
OpenFOAMにおけるDEM計算の衝突モデルの解読
OpenFOAMにおけるDEM計算の衝突モデルの解読OpenFOAMにおけるDEM計算の衝突モデルの解読
OpenFOAMにおけるDEM計算の衝突モデルの解読takuyayamamoto1800
 
第2回 配信講義 計算科学技術特論A (2021)
第2回 配信講義 計算科学技術特論A (2021) 第2回 配信講義 計算科学技術特論A (2021)
第2回 配信講義 計算科学技術特論A (2021) RCCSRENKEI
 
Algebraic DP: 動的計画法を書きやすく
Algebraic DP: 動的計画法を書きやすくAlgebraic DP: 動的計画法を書きやすく
Algebraic DP: 動的計画法を書きやすくHiromi Ishii
 
たのしい高階関数
たのしい高階関数たのしい高階関数
たのしい高階関数Shinichi Kozake
 

Was ist angesagt? (20)

traitを使って楽したい話
traitを使って楽したい話traitを使って楽したい話
traitを使って楽したい話
 
Extensible Effects in Dotty
Extensible Effects in DottyExtensible Effects in Dotty
Extensible Effects in Dotty
 
関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐり関数型プログラミングのデザインパターンひとめぐり
関数型プログラミングのデザインパターンひとめぐり
 
ML Opsのススメ
ML OpsのススメML Opsのススメ
ML Opsのススメ
 
純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門
 
Capabilities for Resources and Effects
Capabilities for Resources and EffectsCapabilities for Resources and Effects
Capabilities for Resources and Effects
 
ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2
ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2
ステップ・バイ・ステップで学ぶラムダ式・Stream api入門 #jjug ccc #ccc h2
 
Comonads in Haskell
Comonads in HaskellComonads in Haskell
Comonads in Haskell
 
最適化計算/パラメータスタディーとFreeCADの連携についての調査
最適化計算/パラメータスタディーとFreeCADの連携についての調査最適化計算/パラメータスタディーとFreeCADの連携についての調査
最適化計算/パラメータスタディーとFreeCADの連携についての調査
 
Boundary Conditions in OpenFOAM
Boundary Conditions in OpenFOAMBoundary Conditions in OpenFOAM
Boundary Conditions in OpenFOAM
 
OpenFOAM の境界条件をまとめよう!
OpenFOAM の境界条件をまとめよう!OpenFOAM の境界条件をまとめよう!
OpenFOAM の境界条件をまとめよう!
 
デザインパターン(初歩的な7パターン)
デザインパターン(初歩的な7パターン)デザインパターン(初歩的な7パターン)
デザインパターン(初歩的な7パターン)
 
Jbatch実践入門 #jdt2015
Jbatch実践入門 #jdt2015Jbatch実践入門 #jdt2015
Jbatch実践入門 #jdt2015
 
Scala 初心者が米田の補題を Scala で考えてみた
Scala 初心者が米田の補題を Scala で考えてみたScala 初心者が米田の補題を Scala で考えてみた
Scala 初心者が米田の補題を Scala で考えてみた
 
OpenFOAMにおけるDEM計算の衝突モデルの解読
OpenFOAMにおけるDEM計算の衝突モデルの解読OpenFOAMにおけるDEM計算の衝突モデルの解読
OpenFOAMにおけるDEM計算の衝突モデルの解読
 
第2回 配信講義 計算科学技術特論A (2021)
第2回 配信講義 計算科学技術特論A (2021) 第2回 配信講義 計算科学技術特論A (2021)
第2回 配信講義 計算科学技術特論A (2021)
 
キメるClojure
キメるClojureキメるClojure
キメるClojure
 
Algebraic DP: 動的計画法を書きやすく
Algebraic DP: 動的計画法を書きやすくAlgebraic DP: 動的計画法を書きやすく
Algebraic DP: 動的計画法を書きやすく
 
Java8勉強会
Java8勉強会Java8勉強会
Java8勉強会
 
たのしい高階関数
たのしい高階関数たのしい高階関数
たのしい高階関数
 

Ähnlich wie 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
 

Ähnlich wie 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