SlideShare una empresa de Scribd logo
1 de 41
Descargar para leer sin conexión
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
おわり

Más contenido relacionado

La actualidad más candente

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
 

La actualidad más candente (20)

php-src の歩き方
php-src の歩き方php-src の歩き方
php-src の歩き方
 
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...The Functional Programming Triad of Folding, Scanning and Iteration - a first...
The Functional Programming Triad of Folding, Scanning and Iteration - a first...
 
Web App Platform Strategy
Web App Platform StrategyWeb App Platform Strategy
Web App Platform Strategy
 
Comonads in Haskell
Comonads in HaskellComonads in Haskell
Comonads in Haskell
 
FSI analysis with preCICE (OpenFOAM and CalculiX)
FSI analysis with preCICE (OpenFOAM and CalculiX) FSI analysis with preCICE (OpenFOAM and CalculiX)
FSI analysis with preCICE (OpenFOAM and CalculiX)
 
스프링 부트와 로깅
스프링 부트와 로깅스프링 부트와 로깅
스프링 부트와 로깅
 
Using PyFoam as library(第25回オープンCAE勉強会@関西)
Using PyFoam as library(第25回オープンCAE勉強会@関西)Using PyFoam as library(第25回オープンCAE勉強会@関西)
Using PyFoam as library(第25回オープンCAE勉強会@関西)
 
[PHP 也有 Day #64] PHP 升級指南
[PHP 也有 Day #64] PHP 升級指南[PHP 也有 Day #64] PHP 升級指南
[PHP 也有 Day #64] PHP 升級指南
 
Fantastic DSL in Python
Fantastic DSL in PythonFantastic DSL in Python
Fantastic DSL in Python
 
Goでヤフーの分散オブジェクトストレージを作った話 Go Conference 2017 Spring
Goでヤフーの分散オブジェクトストレージを作った話 Go Conference 2017 SpringGoでヤフーの分散オブジェクトストレージを作った話 Go Conference 2017 Spring
Goでヤフーの分散オブジェクトストレージを作った話 Go Conference 2017 Spring
 
hbstudy# 28 SELinux HandsOn 公開版
hbstudy# 28 SELinux HandsOn 公開版hbstudy# 28 SELinux HandsOn 公開版
hbstudy# 28 SELinux HandsOn 公開版
 
Beyond Scala Lens
Beyond Scala LensBeyond Scala Lens
Beyond Scala Lens
 
composerの遅さをまじめに考える #phpstudy
composerの遅さをまじめに考える #phpstudycomposerの遅さをまじめに考える #phpstudy
composerの遅さをまじめに考える #phpstudy
 
Djangoフレームワークの紹介
Djangoフレームワークの紹介Djangoフレームワークの紹介
Djangoフレームワークの紹介
 
今さら聞けない人のためのDocker超入門 CentOS 7.2対応版
今さら聞けない人のためのDocker超入門 CentOS 7.2対応版今さら聞けない人のためのDocker超入門 CentOS 7.2対応版
今さら聞けない人のためのDocker超入門 CentOS 7.2対応版
 
RxJS Evolved
RxJS EvolvedRxJS Evolved
RxJS Evolved
 
OpenFOAM の Function Object 機能について
OpenFOAM の Function Object 機能についてOpenFOAM の Function Object 機能について
OpenFOAM の Function Object 機能について
 
OVF, OVA, ovftool
OVF, OVA, ovftoolOVF, OVA, ovftool
OVF, OVA, ovftool
 
HELYX-OS in DEXCS2016 for OpenFOAM
HELYX-OS in DEXCS2016 for OpenFOAMHELYX-OS in DEXCS2016 for OpenFOAM
HELYX-OS in DEXCS2016 for OpenFOAM
 
RxSwift コードリーディングの勘所@社内RxSwift勉強会
RxSwift コードリーディングの勘所@社内RxSwift勉強会RxSwift コードリーディングの勘所@社内RxSwift勉強会
RxSwift コードリーディングの勘所@社内RxSwift勉強会
 

Similar a Extensible Eff Applicative

すごいHaskell 第7章 型や型クラスを自分で作ろう(後編)
すごいHaskell 第7章 型や型クラスを自分で作ろう(後編)すごいHaskell 第7章 型や型クラスを自分で作ろう(後編)
すごいHaskell 第7章 型や型クラスを自分で作ろう(後編)
Nozomu Kaneko
 
すごいHaskell読書会#10
すごいHaskell読書会#10すごいHaskell読書会#10
すごいHaskell読書会#10
Shin Ise
 
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
 

Similar a 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