Stateモナドの例の式のトレース
SEさんは、トレース得意なので
書く必要が無いかもしれませんが
老婆心から。
計算してみると、結構タイヘン。
計算が得意でない人で、初心者ならば
consを3回もしない例で、やった方が良いかも。
こういう計算の支援系はないのかな、自動計算はできなくても
計算ステップの前後でチェックができたり、適用可能な変形の候補を
プログラムの補完機能みたいに、ポップアップで表示するなりできる
ツールは世の中に存在しないのだろうか?
coqは、興味深いけど、ツールの特性に合わせるのがタイヘンだから
この場合の候補には、ならないと思われる。
お題
下記式の簡約のトレース
>run (cons0 "a" Nil >>= cons0 "b" >>= cons0 "c") 0
>→ (Cons "c" (Cons "b" (Cons "a" Nil)),3)
以下トレース実施
(なお、計算順序は、適用の仕方が可笑しくなければ
たぶん、チャーチロッサー性で担保できると思っている)
run (cons0 "a" Nil >>= cons0 "b" >>= cons0 "c") 0
{
cons0の定義より
∵cons0 :: a -> List a -> Monadic (List a)
cons0 x xs = Monadic $ \cnt -> (Cons x xs, cnt + 1)
}
→run ( (Monadic $ \cnt1 -> (Cons "a" Nil, cnt1 + 1))
>>= Monadic (\xs -> \cnt2 -> (Cons "b" xs, cnt2 + 1))
>>= Monadic (\xs -> \cnt3 -> (Cons "c" xs, cnt3 + 1))) 0
→run (Monadic f >>= Monadic g >>= Monadic h) 0
f:(\cnt0 -> (Cons "a" Nil, cnt0 + 1))
g:(\cnt2 -> \xs -> (Cons "b" xs, cnt2 + 1))
h:(\cnt3 -> \ys -> (Cons "c" ys, cnt3 + 1))
{
モナドのbind(>>=)の定義より「Monadic f >>= Monadic g」を展開すると
Monadic f >>= g
= Monadic (\cnt0 ->
let (result1, cnt1) = f cnt0
in run (g result1) cnt1)
}
→run (Monadic (\cnt0 -> let (result1, cnt1) = f cnt0
in run (Monadic g result1) cnt1)
>>= Monadic h) 0
f:(\cnt0 -> (Cons "a" Nil, cnt0 + 1))
g:(\cnt2 -> \xs -> (Cons "b" xs, cnt2 + 1))
h:(\cnt3 -> \ys -> (Cons "c" ys, cnt3 + 1))
→run (Monadic k >>= Monadic h) 0
k:(\cnt0 ->
let (result1, cnt1) = f cnt0
in run (Monadic g result1) cnt1)
{
モナドの定義を変形した下記を使用して展開すると
Monadic k >>= (Monadic h)
= Monadic (\cnt3 ->
let (result4, cnt4) = k cnt3
in run ( (Monadic h) result4) cnt4)
}
→run (Monadic (\cnt3 ->
let (result4, cnt4) = k cnt3
in run (h result4) cnt4)) 0
k:(\cnt0 ->
let (result1, cnt1) = f cnt0
in run (Monadic g result1) cnt1)
→run (Monadic (\cnt3 ->
let (result4, cnt4) = ((\cnt0 ->
let (result1, cnt1) = f cnt0
in run (Monadic g result1) cnt1) cnt3)
in run ( (Monadic h) result4) cnt4)) 0
{
runの定義より
run (Monadic func) initCnt = func initCnt
}
→(\cnt3 ->
let (result4, cnt4) = ( (\cnt0 ->
let (result1, cnt1) = f cnt0
in run (Monadic g result1) cnt1) cnt3)
in run ( (Monadic h) result4) cnt4)) 0
→(\0 ->
let (result4, cnt4) = ( (\cnt0 ->
let (result1, cnt1) = f cnt0
in run (Monadic g result1) cnt1) cnt3)
in run ( (Monadic h) result4) cnt4))
→let (result4, cnt4) = ( (\cnt0 ->
let (result1, cnt1) = f cnt0
in run (Monadic g result1) cnt1) 0)
in run ( (Monadic h) result4) cnt4)
{
runの定義より
run (Monadic func) initCnt = func initCnt
}
→let (result4, cnt4) = ( (\cnt0 ->
let (result1, cnt1) = f cnt0
in (g result1) cnt1) 0)
in run ( (Monadic h) result4) cnt4)
f:(\cnt0 -> (Cons "a" Nil, cnt0 + 1))
g:(\cnt2 -> \xs -> (Cons "b" xs, cnt2 + 1))
h:(\cnt3 -> \ys -> (Cons "c" ys, cnt3 + 1))
→let (result4, cnt4) = ( (\cnt0 ->
let (result1, cnt1) = (\cnt0 -> (Cons "a" Nil, cnt0 + 1)) cnt0
in (g result1) cnt1) 0)
in run ( (Monadic h) result4) cnt4)
g:(\cnt2 -> \xs -> (Cons "b" xs, cnt2 + 1))
h:(\cnt3 -> \ys -> (Cons "c" ys, cnt3 + 1))
→let (result4, cnt4) = ( (\cnt0 ->
let (result1, cnt1) = (Cons "a" Nil, cnt0 + 1)
in (g result1) cnt1) 0)
in run ( (Monadic h) result4) cnt4)
g:(\cnt2 -> \xs -> (Cons "b" xs, cnt2 + 1))
h:(\cnt3 -> \ys -> (Cons "c" ys, cnt3 + 1))
→let (result4, cnt4) = ( (\cnt0 ->
let (result1, cnt1) = (Cons "a" Nil, cnt0 + 1)
in (g (Cons "a" Nil)) cnt0 + 1) 0)
in run ( (Monadic h) result4) cnt4)
g:(\cnt2 -> \xs -> (Cons "b" xs, cnt2 + 1))
h:(\cnt3 -> \ys -> (Cons "c" ys, cnt3 + 1))
→let (result4, cnt4) = ((\cnt0 -> g (Cons "a" Nil) cnt0 + 1) 0)
in run ( (Monadic h) result4) cnt4)
g:(\cnt2 -> \xs -> (Cons "b" xs, cnt2 + 1))
h:(\cnt3 -> \ys -> (Cons "c" ys, cnt3 + 1))
→let (result4, cnt4) = ( (\0 -> g (Cons "a" Nil) cnt0 + 1) 0)
in run ( (Monadic h) result4) cnt4)
g:(\cnt2 -> \xs -> (Cons "b" xs, cnt2 + 1))
h:(\cnt3 -> \ys -> (Cons "c" ys, cnt3 + 1))
→let (result4, cnt4) = (g (Cons "a" Nil) 0 + 1)
in run ( (Monadic h) result4) cnt4)
g:(\cnt2 -> \xs -> (Cons "b" xs, cnt2 + 1))
h:(\cnt3 -> \ys -> (Cons "c" ys, cnt3 + 1))
→let (result4, cnt4) = (g (Cons "a" Nil) 1)
in run ( (Monadic h) result4) cnt4)
g:(\cnt2 -> \xs -> (Cons "b" xs, cnt2 + 1))
h:(\cnt3 -> \ys -> (Cons "c" ys, cnt3 + 1))
→let (result4, cnt4) = ((\cnt2 -> \xs -> (Cons "b" xs, cnt2 + 1)) (Cons "a" Nil) 1)
in run ( (Monadic h) result4) cnt4)
h:(\cnt3 -> \ys -> (Cons "c" ys, cnt3 + 1))
→let (result4, cnt4) = ( (\(Cons "a" Nil) -> \1 -> (Cons "b" xs, cnt2 + 1)) (Cons "a" Nil) 1)
in run ( (Monadic h) result4) cnt4)
h:(\cnt3 -> \ys -> (Cons "c" ys, cnt3 + 1))
→let (result4, cnt4) = ( (\(Cons "a" Nil) -> \1 -> (Cons "b" (Cons "a" Nil), 1 + 1)) (Cons "a" Nil) 1)
in run ( (Monadic h) result4) cnt4)
h:(\cnt3 -> \ys -> (Cons "c" ys, cnt3 + 1))
→let (result4, cnt4) = (Cons "b" (Cons "a" Nil), 1 + 1)
in run ( (Monadic h) result4) cnt4)
h:(\cnt3 -> \ys -> (Cons "c" ys, cnt3 + 1))
→let (result4, cnt4) = (Cons "b" (Cons "a" Nil), 2)
in run ( (Monadic h) result4) cnt4)
h:(\cnt3 -> \ys -> (Cons "c" ys, cnt3 + 1))
→let (result4, cnt4) = (Cons "b" (Cons "a" Nil), 2)
in run ( (Monadic h) (Cons "b" (Cons "a" Nil))) 2)
h:(\cnt3 -> \ys -> (Cons "c" ys, cnt3 + 1))
{
runの定義より
run (Monadic func) initCnt = func initCnt
}
→let (result4, cnt4) = (Cons "b" (Cons "a" Nil), 2)
in h (Cons "b" (Cons "a" Nil))) 2)
h:(\cnt3 -> \ys -> (Cons "c" ys, cnt3 + 1))
→let (result4, cnt4) = (Cons "b" (Cons "a" Nil), 2)
in (\cnt3 -> \ys ->
(Cons "c" ys, cnt3 + 1))) (Cons "b" (Cons "a" Nil))) 2)
→let (result4, cnt4) = (Cons "b" (Cons "a" Nil), 2)
in (\2 -> \(Cons "b" (Cons "a" Nil))) ->
(Cons "c" ys, cnt3 + 1))) (Cons "b" (Cons "a" Nil))) 2)
→let (result4, cnt4) = (Cons "b" (Cons "a" Nil), 2)
in (\2 -> \(Cons "b" (Cons "a" Nil))) ->
(Cons "c" (Cons "b" (Cons "a" Nil))), 2 + 1))) (Cons "b" (Cons "a" Nil))) 2)
→let (result4, cnt4) = (Cons "b" (Cons "a" Nil), 2)
in (Cons "c" (Cons "b" (Cons "a" Nil))), 3)))
→(Cons "c" (Cons "b" (Cons "a" Nil))), 3)))
大筋こんな感じ ?
間違いを見つけて後で書き直すかもしれない。
→修正した。たぶんあっている。
以上です。