プログラムのデバッグ支援

Yasutaka Higa

プログラムのデバッグ支援

研究目的

  • プログラミングにおいて、ソースコードを改変するとプログラムの挙動も変わる
  • しかしリファクタリングにおいてはソースコードを変更した後も同じ結果を得たい
  • ソースコードの改変をモナドとして記述し、実行結果の変化を自動的に検出したい
  • これによりリファクタリング支援や後方互換性の支援などを行なう

近況報告

  • Deifine Simple Similar
    • Similar
    • Similar as Functor
    • Similar as Applicative Functor
    • Similar as Monad

Similar

  • List みたいな感じになりました
data Similar a = Single a | Similar a (Similar a)
  • オリジナルの関数は Single で値を包んでおく必要がある
    • 全てはモナド、って伏線がここで
  • 似てる関数は、その値を a に、とオリジナルの関数をsimilarする

Similar Syntax

  • オリジナルの関数は Single で値を包んでおく必要がある
    • こうしておかないと、リファクタリング時にオリジナルの関数を修正する必要が出てくる
    • とは言え関数を呼び出す側は変更しなくてはならないのでリファクタリング時にプログラムが全く変更されない訳では無い
  • その変わり「関数Aをリファクタリングした関数Bをリファクタリングした関数C」も扱える

Similar Syntax Example

double :: Int -> Similar Int
double x = Single (2 * x)

twicePlus :: Int -> Similar Int
twicePlus x = Similar (x + x) (double x)

Similar as Functor

  • Functor は関数 f を全ての要素に与える
    • List っぽい
instance Functor Similar where
   fmap f (Single a)    = Single (f a)
   fmap f (Similar a s) = Similar (f a) (fmap f s)

Similar as Monad

  • mu は Similar (Similar a) -> Similar a
  • List の List みたいな感じで一旦 flatten する必要が
  • Similar (Similar a) はこんなの
Similar (Single (Similar 1 (Single 1)))
        (Single (Single (Similar 1 (Single 1))))

Definition : mu

mu :: (Similar (Similar a)) -> Similar a
mu (Single s)     = s
mu (Similar s ss) = similar s (mu ss)
  • similar は list で言う append みたいな
  • mu の中で変更を検出しても良いが Eq の instance である必要がある
  • なので最後の時に値比較をすることに
    • 値比較 + debugger で追いたい情報を埋めこんでおくと良い?

Definition : Similar as Monad

instance Monad Similar where
    return              = Single
    (Single x)    >>= f = f x
    (Similar x s) >>= f = mu $ Similar (f x) (fmap f s)
  • Similar (f x) (fmap f s) の type が (Similar (Similar a))

Get value : Similar

same :: (Eq a) => Similar a -> a
same (Single x)    = x
same (Similar x s) = if x == (same s) then x else (error "same")
  • 今は値が違う、というエラーメッセージのみ

Get value : Similar

  • こっちは値比較無し
  • 問答無用で正しく動いている方を取る
value :: Similar a -> a
value (Single x)    = x
value (Similar x s) = value s

Execution Samples : bind

*Main>  return 100 >>= double  >>= twicePlus
Similar 400 (Single 400)
*Main>  return 100 >>= double  >>= twicePlus >>= plusTwo
Similar 402 (Similar 800 (Similar 402 (Single 800)))

Execution Samples : Get value

*Main> same $  return 100 >>= double  >>= twicePlus >>= plusTwo
*** Exception: same
*Main> same $  return 100 >>= double  >>= twicePlus
400

Similar as Applicative Functor

  • ghc 7.8.3 から Monad の instance にするには Applicative にもしておくこと推奨
  • Similar 内に function が入ってる場合の挙動
    • T f みたいな状態
  • こっちも List っぽい感じで全てのパターンを作ってしまう

Define : Similar as Applicative Functor

instance Applicative Similar where
    pure                 = Single
    (Single f)    <*> s  = fmap f s
    (Similar f s) <*> ss = similar (fmap f ss) (s <*> ss)

summary

  • List (non-deterministic Monad) っぽい
    • debugger info の埋め込み
    • どんな関数がどんな順番で呼ばれたか
  • Functor raw, Monad raw
    • 証明しておく必要が
    • 特に Monoid なのかどうか