普遍的なポリモーフィズムの機能を考慮して、再帰代数データ型の定義、逆変換、およびエンコードを理解しようとしています。例として、次の方法で再帰的な二分木の実装を試みました。
data BTAlg x = Empty | Leaf x x
type BT = forall z. ((BTAlg z) -> z) -> z
二分木のタイプはT
、定数e: T
と二分演算を備えたすべてのタイプm: T -> T -> T
、つまり functor の「初期モジュール」を備えたすべてのタイプの中で初期化する必要があるという直感BTAlg
です。つまり、 の要素BT
は、そのようなモジュールT
に対して の要素を割り当てる方法ですT
。
それ自体のモジュール構造は、次のBT
方法で定義できます。
initial_module :: (BTAlg BT) -> BT
initial_module = \s -> case s of
Empty -> (\f -> (f Empty))
Leaf x y -> (\f -> (f (Leaf (x f) (y f))))
のパターン マッチングに向けたステップとして、型自体にBT
要素を適用したいと思います。これは、 の何らかのエンコード/デコードと考えられます。x:BT
BT
x
decode_encode :: BT -> BT
decode_encode x = x initial_module
ただし、このコードでは、処理できない型エラーが発生します。
Couldn't match expected type `(BTAlg z -> z) -> z'
with actual type `BT'
Expected type: BTAlg ((BTAlg z -> z) -> z) -> (BTAlg z -> z) -> z
Actual type: BTAlg BT -> (BTAlg z0 -> z0) -> z0
In the first argument of `x', namely `initial_module'
In the expression: x initial_module
ここで何が問題なのですか?に適用できるようにするには、ユニバーサル型パラメーターz
をに特化する必要があることを型チェッカーが認識しない理由がわかりません。書くことも役に立ちません。BT
x
x
initial_module
(x :: ((BTAlg BT) -> BT) -> BT) initial_module
定義の動機に関する補遺decode_encode
:BT
標準実現と実際に「同型」であることを自分自身に納得させたい
data BTStd = StdEmpty | StdLeaf BTStd BTStd
二分木の; Haskell内でこれを正確にする方法はわかりませんが、最初はマップBT -> BTStd
を作成BTStd -> BT
し、2つの実現の間を行き来することです。
の定義は、 の標準モジュール構造にtoStandard: BT -> BTStd
の普遍的なプロパティを適用したものです。BT
BTAlg
BTStd
std_module :: (BTAlg BTStd) -> BTStd
std_module s = case s of
Empty -> StdEmpty
Leaf x y -> StdLeaf x y
toStandard: BT -> BTStd
toStandard x = x std_module
デコード機能についてfromStandard: BTStd -> BT
は、次のことを行いたいと思います。
fromStandard :: BTStd -> BT
fromStandard s = case s of
StdEmpty -> initial_module Empty
StdLeaf x y -> initial_module (Leaf (fromStandard x) (fromStandard y))
decode_encode
ただし、これにより、上記の直接定義と同じタイプの問題が発生します。
Couldn't match expected type `BT'
with actual type `(BTAlg z0 -> z0) -> z0'
In the return type of a call of `fromStandard'
Probable cause: `fromStandard' is applied to too few arguments
In the first argument of `Leaf', namely `(fromStandard x)'
In the first argument of `initial_module', namely
`(Leaf (fromStandard x) (fromStandard y))'
ありがとうございました!