ch21 再帰型のメタ理論
gfp
def 21.5.5
よって、
Haskell 実装
gfp :: InferRule -> Universe -> Bool
gfp rule setX
| isNothing setX' = False
| fromJust setX' `Set.isSubsetOf` setX = True
| otherwise = gfp rule (fromJust setX' `Set.union` setX)
where
setX' = supportSet rule setX
gfp の問題点
余分な再計算が起こる。
gfp^{a}
def 21.6.1 各要素の支持集合を高々1回しか計算しないバージョン。
- | - | - |
よって、
Haskell 実装
gfpA :: InferRule -> Universe -> Bool
gfpA rule setX = gfpA' rule (Set.empty, setX)
gfpA' :: InferRule -> (Universe, Universe) -> Bool
gfpA' rule (setA, setX)
| isNothing setX' = False
| Set.null setX = True
| otherwise = gfpA' rule (setAX, fromJust setX' `Set.difference` setAX)
where
setAX = setA `Set.union` setX
setX' = supportSet rule setX
gfp^{s}
def 21.6.3 - | - | - | - | - |
よって、
- | - | - | - | - |
memo
Haskell 実装
gfpS :: InferRule -> Universe -> Bool
gfpS rule setX = gfpS' rule (Set.empty, setX)
gfpS' :: InferRule -> (Universe, Universe) -> Bool
gfpS' rule (setA, setX)
| Set.null setX = True
| Set.member x setA = gfpS' rule (setA, setX `Set.difference` Set.singleton x)
| isNothing setX' = False
| otherwise = gfpS' rule (setAx, (setX `Set.union` fromJust setX') `Set.difference` setAx)
where
x = Set.elemAt 0 setX
setAx = setA `Set.union` Set.singleton x
setX' = supportSet rule setX
gfp^{t}
def 21.6.4 引数を集合では無く候補となる要素1つだけを取るようにしたバージョン。
変更点
- 末尾再帰ではなくなる
- 返り値が仮定の集合
- | |||||||
- | |||||||
- | |||||||
- | - | - | - |
この段階で
- | |||||||
- | - |
ここで
- | - | - | - |
ここで
よって
Haskell 実装
gfpT :: InferRule -> Element -> Bool
gfpT rule x = isJust $ gfpT' rule (Just Set.empty, x)
gfpT' :: InferRule -> (Maybe Universe, Element) -> Maybe Universe
gfpT' rule (mSetA, x) = do
setA <- mSetA
if Set.member x setA
then mSetA
else do
xs <- Set.toList <$> support rule x
let a0 = setA `Set.union` Set.singleton x
go = flip $ curry $ gfpT' rule
foldr go (Just a0) xs
TODO: BNF, (可逆な)生成関数, 推論規則, 支持関数 の繋がりについてまとめる
lfp
ex 21.5.13 最大不動点ではなく、最小不動点の所属性検査を行う関数。
- 与えられた要素が循環に含まれるか、循環に含まれる要素に依存している場合に無限ループになり、実行が止まらなくなる
- |
よって
循環の場合は以下のように無限ループする。
Haskell 実装
lfp :: InferRule -> Universe -> Bool
lfp rule setX
| isNothing setX' = False
| Set.null (fromJust setX') = True
| otherwise = lfp rule (fromJust setX')
where
setX' = supportSet rule setX
lfp 問題点
- 余分な再計算が起こる。
- 循環や無限列が含まれる場合に停止しない
lfp^{a}
-
のようにgfp^{a} に対しても仮定の集合を持つようにしたバージョンlfp - 循環を扱えるようになる
定義
TODO
Haskell 実装
lfpA :: InferRule -> Universe -> Bool
lfpA rule setX = lfpA' rule (Set.empty, setX)
lfpA' :: InferRule -> (Universe, Universe) -> Bool
lfpA' rule (setA, setX)
| isNothing setX' = False
| setA == (setA `Set.union` setX) = Set.null setX -- 循環チェック
| otherwise = lfpA' rule (setA `Set.union` (setX `Set.difference` fromJust setX'), fromJust setX')
where
setX' = supportSet rule setX
lfp^{a} の問題点
- 余分な再計算が起こる
- 無限列に対しては停止しない
suport
def 21.5.1 可逆と TODO