(手動導出のためにスキップします)
与えられたhead . filter fst
==の型を見つける((.) head) (filter fst)
head :: [a] -> a
(.) :: (b -> c) -> ((a -> b) -> (a -> c))
filter :: (a -> Bool) -> ([a] -> [a])
fst :: (a, b) -> a
これは、小さな Prolog プログラムによって純粋に機械的な方法で実現されます。
type(head, arrow(list(A) , A)). %% -- known facts
type(compose, arrow(arrow(B, C) , arrow(arrow(A, B), arrow(A, C)))).
type(filter, arrow(arrow(A, bool), arrow(list(A) , list(A)))).
type(fst, arrow(pair(A, B) , A)).
type([F, X], T):- type(F, arrow(A, T)), type(X, A). %% -- application rule
Prologインタープリターで実行すると、自動的に生成されます
3 ?- type([[compose, head], [filter, fst]], T).
T = arrow(list(pair(bool, A)), pair(bool, A)) %% -- [(Bool,a)] -> (Bool,a)
ここで、型は、純粋に構文上の方法で、複合データ用語として表されます。たとえば、適切な定義が与えられた場合、型[a] -> a
は で表されarrow(list(A), A)
、Haskell の同等の可能性がある で表されます。Arrow (List (Logvar "a")) (Logvar "a")
data
1 つの推論規則、アプリケーションの推論規則のみが使用され、Prolog の構造統一が使用されました。これにより、複合項が同じ形状を持ち、それらの構成要素が一致する場合に一致します: f(a 1 , a 2 , ... a n )およびg (b 1 , b 2 , ... b m ) fがg , n == mと同じであり、a iがb iと一致する場合に一致 します。論理変数は必要に応じて任意の値を取ることができますが、一度だけです。(変更できません)。
4 ?- type([compose, head], T1). %% -- (.) head :: (a -> [b]) -> (a -> b)
T1 = arrow(arrow(A, list(B)), arrow(A, B))
5 ?- type([filter, fst], T2). %% -- filter fst :: [(Bool,a)] -> [(Bool,a)]
T2 = arrow(list(pair(bool, A)), list(pair(bool, A)))
機械的な方法で手動で型推論を実行するには、物事を下に書き、側面の同等性に注意し、置換を実行して、Prolog の操作を模倣する必要があります。any ->, (_,_), []
etc. を純粋に構文マーカーとして扱い、その意味をまったく理解せずに、構造の統一を使用して機械的にプロセスを実行できます。ここでは、型推論の 1 つのルールのみを使用します。適用規則: ( との並置をとに(a -> b) c ⊢ b {a ~ c}
置き換えます)。名前の衝突を避けるために、一貫して論理変数の名前を変更することが重要です。(a -> b)
c
b
a
c
(.) :: (b -> c ) -> ((a -> b ) -> (a -> c )) b ~ [a1],
head :: [a1] -> a1 c ~ a1
(.) head :: (a ->[a1]) -> (a -> c )
(a ->[c] ) -> (a -> c )
---------------------------------------------------------
filter :: ( a -> Bool) -> ([a] -> [a]) a ~ (a1,b),
fst :: (a1, b) -> a1 Bool ~ a1
filter fst :: [(a1,b)] -> [(a1,b)]
[(Bool,b)] -> [(Bool,b)]
---------------------------------------------------------
(.) head :: ( a -> [ c ]) -> (a -> c) a ~ [(Bool,b)]
filter fst :: [(Bool,b)] -> [(Bool,b)] c ~ (Bool,b)
((.) head) (filter fst) :: a -> c
[(Bool,b)] -> (Bool,b)