通常の関数を取り、それらを抽象値の計算に変換するアロートランスフォーマーを作成しようとしています。「ソース」矢印がある場合、
f :: Int -> Int
f x = x + 1
次に、この例では、リフトされた [sic?] 抽象値型でfを機能させることが目標になります。
f' :: AV Int -> AV Int
f' (Const x) = Const (f x)
-- pass along errors, since AV computation isn't always defined
-- or computable in the case of errors
f' (Error s) = Error s
-- avRep = "abstract representation". Think of symbolic math manipulation or ASTs.
f' (Abstract avRep) = AVRepPlus avRep (AVRepConst 1)
ただし、この矢印をうまく実装するには、いくつかの型を持ち上げて、任意の深さでいくつかの具体的な値といくつかの抽象値を持つ異種データ構造を持つようにする必要があります。私がやったことは、通常のhaskellコンストラクターに特別なタイプを追加することです。
g = uncurry (+) -- i.e. g (x, y) = x + y
次に、タプル コンストラクターである (,) の抽象表現を追加します。
AVTuple :: AV a -> AV b -> AV (a, b)
gのコードは[少し展開] に持ち上げられ、
g' (AVTuple (AVConst a) (AVConst b)) = (AVConst (g (a, b)))
g' (AVTuple (AVError e) _) = (AVError e)
-- symmetric case here, i.e. AVTuple _ (AVError e)
g' (AVTuple a@(AVTuple _ _) b) = -- recursive code here
同じことを AVEither で行う必要があります。これは多くのケースで終わるでしょう。これを回避する良い方法はありますか?
私は Haskell の初心者なので、参考文献または半詳細な説明を送ってください。おそらく私が読んだ中で最も近いのは、SYBR の論文 (ボイラープレートの革命を破棄する) のセクション 1 ~ 3 です。
本当にありがとう!