ここには示されていない無関係のコード部分に使用するGADT拡張機能でコンパイルするときに、タイプエラーが発生するため、以下の関数が拒否されます。教会のコード変換機能がGADTでコンパイルできない
newtype Church = Church { unC :: forall a. (a -> a) -> a -> a }
to_c :: Int -> Church
to_c 0 = let f0 f c = c in Church f0
to_c n =
let fn f c = iterate f c !! n in Church fn
エラーメッセージ:
Couldn't match type ‘a0’ with ‘a’ because type variable ‘a’ would escape its scope
This (rigid, skolem) type variable is bound by
a type expected by the context:
(a -> a) -> a -> a
Expected type: (a -> a) -> a -> a
Actual type: (a0 -> a0) -> a0 -> a0
In the first argument of ‘Church’, namely ‘fn’
は、私は仕事もチェックして入力します直接の再帰的なスタイルで関数を書き換えることができます。しかし、なぜこの反復的なアプローチに欠陥があるのか、そしてそれが巧妙な型の注釈で救済できるのかどうか不思議でした。
この場合、特にローカルバインディングに実際にGADTが含まれていないため、MonoLocalBindsは非常に制限的です。 GHCがよりリラックスしたアプローチを使用できるかどうかは疑問です。 – chi
@chi、多分。しかし、ユーザがいつ推論が成功するかを予測できることが重要です。 'MonoLocalBinds'は既に多義性を許そうとしているので、理解しにくいです。より巧妙な音を危険にさらす。 – dfeuer