私は自分のプログラムで実存的なタイプに苦労しています。私は非常に合理的なことをしようとしていると思いますが、タイプチェッカーを乗り越えることはできません:(
モナドを模倣したデータ型があります
data M o = R o | forall o1. B (o1 -> M o) (M o1)
ここで、 Zipperに関するHaskell Wikiの記事で説明されているものと同様のコンテキストを作成しますが、簡単にするためにデータ構造の代わりに関数を使用します-
type C o1 o2 = M o1 -> M o2
データ値をコンテキストとサブ値に分割する関数を作成しようとすると、タイプチェッカーは次のように文句を言います。
ctx :: M o -> (M o1 -> M o, M o1)
ctx (B f m) = (B f, m) -- Doesn't typecheck
エラーは-
Couldn't match type `o2' with `o1'
`o2' is a rigid type variable bound by
a pattern with constructor
B :: forall o o1. (o1 -> M o) -> M o1 -> M o,
in an equation for `ctx'
at delme1.hs:6:6
`o1' is a rigid type variable bound by
the type signature for ctx :: M o -> (M o1 -> M o, M o1)
at delme1.hs:6:1
Expected type: M o2
Actual type: M o1
In the expression: m
In the expression: (B f, m)
しかし、私はそのようにそれを回避することができます-
ctx (B f m) = let (c,m') = ctx m in ((B f) . c, m') -- OK
なぜこの2番目の定義はタイプチェックするのに、最初の定義はタイプチェックしないのですか?
また、Rをチェックして完全な関数に変換しようとするctx
と、タイプチェックエラーが再び発生します-
ctx (R o) = (id, R o) -- Doesn't typecheck
エラー -
Couldn't match type `o' with `o1'
`o' is a rigid type variable bound by
the type signature for ctx :: M o -> (M o1 -> M o, M o1)
at delme1.hs:7:1
`o1' is a rigid type variable bound by
the type signature for ctx :: M o -> (M o1 -> M o, M o1)
at delme1.hs:7:1
In the first argument of `R', namely `o'
In the expression: R o
In the expression: (id, R o)
このエラーを回避するにはどうすればよいですか?
どんな助けでも大歓迎です!