いくつかの型署名を追加しましょう:
type Nat a = (a -> a) -> a -> a
zero :: Nat a
zero = (\f z -> z)
one :: Nat a
one = (\f z -> f z)
two :: Nat a
two = (\f z -> f (f z))
iszero :: Nat (a -> a -> a) -> a -> a -> a
iszero = (\n -> n (\x -> (\x y -> y)) (\x y -> x))
mult :: Nat a -> Nat a -> Nat a
mult = (\m n -> (\s z -> m (\x -> n s x) z))
ご覧のとおり、のタイプを除いて、すべてがかなり正常に見えますiszero
。
あなたの表現で何が起こるか見てみましょう:
*Main> :t (\n -> (iszero n) one n)
<interactive>:1:23:
Occurs check: cannot construct the infinite type:
a0
=
((a0 -> a0) -> a0 -> a0)
-> ((a0 -> a0) -> a0 -> a0) -> (a0 -> a0) -> a0 -> a0
Expected type: Nat a0
Actual type: Nat (Nat a0 -> Nat a0 -> Nat a0)
In the third argument of `iszero', namely `(mult n one)'
In the expression: (iszero n) one (mult n one)
Nat
エラーがエイリアスをどのように使用しているかを確認してください。
より単純な式を使用すると、実際に同様のエラーが発生する可能性があります\n -> (iszero n) one n
。これが問題です。を呼び出しているのでiszero n
、が必要n :: Nat (b -> b -> b)
です。また、iszero
s型のため、2番目と3番目の引数、n
およびone
、は型がである必要がありb
ます。これで、次のタイプの2つの方程式ができましたn
。
n :: Nat (b -> b -> b)
n :: b
和解することはできません。残念。