Freeモナド
Monad型クラス
自由モナド
任意のFunctor型クラスをMonadにすることができる
Free型
code:purs(hs)
data Free f a = Pure a
| Join (f (Free f a))
Free型はMonadをdata構造として表現したものである
データ型の定義自体にはfにFunctorの制約はない
f :: * -> *ではある
Joinの部分の値コンストラクタにもFreeという名前を使うことが多いが、分かりづらいmrsekut.icon
型コンストラクタと値コンストラクタの名前の重複によって再帰が見づらい
Monadとなる条件とのアナロジーがわかりづらい
だから、PureとJoinという名前を使ったほうが親切だと思うmrsekut.icon
HaskellでのFreeモナドの定義 ref
Freeの構成を、PureとJoinでした場合の定義
code:hs
data Free f a = Pure a
| Join (f (Free f a))
instance Functor f => Functor (Free f) where
fmap = (<$>)
-- fmap f (Pure x) = Pure $ f x
-- fmap f (Join fx) = Join $ fmap (fmap f) fx
instance (Functor f) => Applicative (Free f) where
pure = Pure
Pure f <*> a = fmap f a
Join f <*> a = Join $ fmap (<*> a) f
instance Functor f => Monad (Free f) where
return = Pure
Pure x >>= f = f x
Join x >>= f = Join $ fmap (>>= f) x
これが最も一般的mrsekut.icon
FreeをPureとBindで構成した場合
code:hs
data Free f a where
Pure :: a -> Free f a
Bind :: f x -> (x -> Free f a) -> Free f a
instance Functor (Free f) where
fmap = (<$>)
instance Applicative (Free f) where
pure = Pure
f <*> x = f >>= \f' -> x >>= \x' -> pure $ f' x'
instance Monad (Free f) where
return = Pure
(>>=) (Pure a) a2fb = a2fb a
(>>=) (Bind fx x2fa) a2fb = Bind fx (a2fb <=< x2fa)
ref Free型はMonadをdata構造として表現したもの
Monadとなる条件を考えると、PureとBindで十分なので、「fがFunctorである」という条件は不要になる
参考
Haskell for all: Why free monads matter
不動点の話からFreeの話へ繋げる
自動的にAlgebraic Effects and Handlersなどへの伏線となってる感があるmrsekut.icon
Freeモナドって何なのさっ!? - capriccioso String Creating(Object something){ return My.Expression(something); }
わかりやすいmrsekut.icon
説明がそれなりに簡潔で良い
出てくるコードは上のHaskell for allの類似
Freeモナドのしくみ - Qiita
かなり親切で詳細
これ読んだおかげで細かい箇所の解像度が上がったmrsekut.icon
free monadとはmonadそのものである - うさぎ小屋
Freeモナドの4種の定義
#WIP
ArchitectureとしてのFreeモナド
lotz (@lotz84_)
"String Diagrams for Free Monads"
Freeモナドの持つ外延的な性質(emb, interp)をストリング図に落とし込むことでFreeモナドやFreeモナドトランスフォーマーの満たす性質をストリング図で証明する話
https://research-information.bris.ac.uk/ws/portalfiles/portal/87127912/Nicolas_Wu_String_Diagrams_for_Free_Monads.pdf
圏論
https://qiita.com/karrym/items/41cd9facae3a04d97703
https://hiratara.hatenadiary.jp/entry/20121011/1349921356
https://ncatlab.org/nlab/show/free+monad
https://halcat.org/scala/freeap/index.html
https://zenn.dev/funnycat/articles/a8eb151c2f9a35
pursの場合
https://pursuit.purescript.org/packages/purescript-free/6.0.1/docs/Control.Monad.Free
むかし
https://github.com/purescript/purescript-free/blob/9999ba1a07f26b440a91155717b2988a88d00bcb/src/Control/Monad/Free.purs
code:purs(hs)
-- Type
data Free f a = Free (FreeView f Val Val) (CatList (ExpF f))
data FreeView f a b = Return a
| Bind (f b) (b -> Free f a)
newtype ExpF f = ExpF (Val -> Free f Val)
data Val
-- Functor
instance Functor (Free f) where
map f k = f <$> k
-- Apply
instance Apply (Free f) where
apply = ap
-- Bind
instance Bind (Free f) where
bind (Free v s) k = Free v (snoc s (ExpF (unsafeCoerceBind k)))
where
unsafeCoerceBind :: forall a b. (a -> Free f b) -> Val -> Free f Val
unsafeCoerceBind = unsafeCoerce
-- Applicative
instance Applicative (Free f) where
pure = fromView <<< Return
-- Monad
instance Monad (Free f)
データ型が複雑になっている理由を解明したい #??
https://zenn.dev/funnycat/articles/8660a8baccd5fc
ここにかいてた
Free (f (Free f a))って、Free メイン (続きの計算)ってかんじなのか?
fの無数の入れ子をFreeと見ることが出来る
f aもFree
f f f f ff f f f f faもFree
というか、このネストを潰せる、という性質はMonadにもあったもの
Free fはモナドにできるが、Free自体もモナドらしい ref
よくわからんmrsekut.icon
どのへんが「Free」なのか
https://fumieval.hatenablog.com/entry/20121111/1352614885
https://blog.functorial.com/posts/2012-07-22-What-Makes-The-Free-Monad-Free.html
https://viercc.github.io/blog/posts/2022-03-11-maybe-is-free.html
Maybe == Free Proxy
pursでの実装
pursではちょっと外見が異なる
code:purs(hs)
data Free f a = Free (FreeView f Val Val) (CatList (ExpF f))
Free fだけでなく、Freeそれ自体もmonad
https://qiita.com/hennin/items/c02ae17cac00494a0f56
Freeモナドって何なのさっ!? - capriccioso String Creating(Object something){ return My.Expression(something); }
code:hs
data MyProgram n = Old Int n | Hey n | Hello n | GoodBye
instance Functor MyProgram where
fmap f (Old o n) = Old o (f n)
fmap f (Hey n) = Hey (f n)
fmap f (Hello n) = Hello (f n)
fmap f GoodBye = GoodBye
runProgram :: Show r => Free MyProgram r -> IO ()
runProgram (Free (Old o n)) = putStrLn ("I'm " ++ show o ++ " years old") >> runProgram n
runProgram (Free (Hey n)) = putStrLn "Hey!!!" >> runProgram n
runProgram (Free (Hello n)) = putStrLn "Hello!!!" >> runProgram n
runProgram (Free GoodBye) = putStrLn "GoodBye!!!"
runProgram (Pure r) = putStrLn $ "return " ++ show r
pg :: Free MyProgram ()
pg = do
Free $ Hey (Pure ())
Free $ Hello (Pure ())
Free $ Old 2 (Pure ())
Free GoodBye
main :: IO ()
main = runProgram pg
不動点との関係
data Fix f = Fix (f (Fix f))
https://ilyaletre.hatenablog.com/entry/2018/03/20/224320
https://www.haskellforall.com/2012/06/you-could-have-invented-free-monads.html
todos
pursのFreeの構成の意味
Stackless Scala With Free Monads
Stack Safety for Free
Trampolineモナド
FreeT
TrampolineモナドとFreeTどっちを使うのか
コンパイル後JSでどんなふうに変わっているのか観察
関連
Data.CatList
Control.Monad.Free.Church
処理効率を考えて実装されたFreeモナド
Control.Monad.Free.TH
ASTのデータ型からFreeのアクションを導出する
Coyoneda
Cofree
Operationalモナド
Trampolineモナド
Idetalモナド
Implicit Recursive Slowdown
自由モノイド
自由マグマ
Freerモナド
Free Applicative Functor
Reflection without remorse
/haskell-shoen/Freeモナド
http://okmij.org/ftp/Haskell/zseq.pdf
Asymptotic Improvement of Computations over Free Monads
論文
https://www.researchgate.net/publication/221440256_Asymptotic_Improvement_of_Computations_over_Free_Monads
ユースケース
Trampolineモナド
2Dゲーム
https://hackage.haskell.org/package/free-game
https://fumieval.hatenablog.com/entry/2013/01/09/211215
DSLを作る
http://lqtmirage.hatenablog.com/entry/2018/06/18/182130
https://qiita.com/hiruberuto/items/3d55b0e54565dbb286a7
DSLがいまいちピンときていないmrsekut.icon
Parsecみたいに、Parser ..という型で区切られた世界のこととかをそう呼んでるのか?
普通に型で区切られた世界とどう違うのか
あ、普通にMonadを作ることをDSL作成と言ってるだけか
「Monadを作ること」が「DSLを作ること」にほぼ同じなのであれば、「Freeモナドを作ることの嬉しさ」として「DSLを作れること」って挙げるのおかしくない?
あくまでも「Freeモナドの嬉しさ」は「簡単にモナドを作れること」であって、
「DSLを作ること」は「Monadの嬉しさ」の一つに過ぎないだろう
でもまあFree型はMonadをdata構造として表現したものだから、「Freeモナドの嬉しさ」は「Monadの嬉しさ」と表裏一体だから、結局は同じことなのか。たしかに。
Haskellは言語内DSLを書くのに優れている
Monad構造を動的に操作する例
Free型はMonadをdata構造として表現したものなので、Lispのように同図像性を、型安全に持ったことになる
それを使ってデータの操作をした有用な例みたいなのを見てみたい
ps
https://pursuit.purescript.org/packages/purescript-free/4.0.0/docs/Control.Monad.Free#t:Free
https://github.com/purescript/purescript-free
/herp-technote/Free monad
/haskell-shoen/Freeモナド
https://serokell.io/blog/introduction-to-free-monads
https://monadplus.pro/haskell/2022/04/19/free-interpreter/
https://viercc.github.io/blog/posts/2020-08-23-fmonad.html
chrome-extension://oemmndcbldboiebfnladdacbdfmadadm/http://functorial.com/stack-safety-for-free/index.pdf
https://pursuit.purescript.org/packages/purescript-free/6.0.1/docs/Control.Monad.Trampoline
https://github.com/purescript/purescript-free
chrome-extension://oemmndcbldboiebfnladdacbdfmadadm/http://functorial.com/stack-safety-for-free/index.pdf
https://eed3si9n.com/herding-cats/ja/tail-recursive-monads.html
https://uid0130.blogspot.com/2013/07/trampoline.html
https://eed3si9n.com/herding-cats/ja/stackless-scala-with-free-monads.html
https://eed3si9n.com/learning-scalaz/ja/Stackless+Scala+with+Free+Monads.html
https://halcat.org/scala/stackless/index.html
https://qiita.com/dashiishida/items/c20d6e08a260e3ce0f64
https://free.cofree.io/2017/08/24/trampoline/
https://qiita.com/yyu/items/f1601749097ba3ee03db
https://niyarin.github.io/contents/2019-12/my-scm-plan.html
https://gitter.im/purescript/purescript?at=572939c172798bd77be9c0f0
https://qiita.com/torao@github/items/4b224489c71bf460ad7c
chrome-extension://oemmndcbldboiebfnladdacbdfmadadm/https://blog.higher-order.com/assets/trampolines.pdf
https://scrapbox.io/herp-technote/Free_monad
https://www.haskellforall.com/2012/06/you-could-have-invented-free-monads.html
https://fumieval.hatenablog.com/entry/20121111/1352614885
https://qiita.com/YoshikuniJujo/items/c71644b5af1f5195cbf3
https://blog.functorial.com/posts/2012-07-22-What-Makes-The-Free-Monad-Free.html
https://github.com/shiatsumat/wiwinwlh-jp/wiki/%E9%AB%98%E5%BA%A6%E3%81%AA%E3%83%A2%E3%83%8A%E3%83%89#free-monads
https://zenn.dev/zecl/books/d535208d9f6176/viewer/93d6b0
https://ro-che.info/articles/2013-03-31-flavours-of-free-applicative-functors
https://elvishjerricco.github.io/2016/04/08/applicative-effects-in-free-monads.html
https://qiita.com/goldarn_ring/items/1c895292ae313b74a410
http://lotz84.github.io/haskell/free-monad.html
https://scrapbox.io/haskell-shoen/Free%E3%83%A2%E3%83%8A%E3%83%89
http://comonad.com/reader/2008/monads-for-free/
https://leanpub.com/purescript/read#leanpub-auto-domain-specific-languages
https://qiita.com/hiruberuto/items/3d55b0e54565dbb286a7
https://eng-blog.iij.ad.jp/archives/3467
https://pursuit.purescript.org/packages/purescript-free/4.0.1/docs/Control.Monad.Free#t:Free
https://pursuit.purescript.org/packages/purescript-catenable-lists/6.0.1/docs/Data.CatList#t:CatList
https://github.com/purescript/purescript-catenable-lists
https://twitter.com/hennin_ltn/status/1189295895382241285
https://zenn.dev/lotz/articles/56671def583c58612361
実用例