私はジッパーをいじっています。現在の要素は、左右のリストとは異なるタイプを持つことができます。
data Z a b = Z ([a], b, [a])
moveLeft
とでジッパーをナビゲートできますmoveRight
:
moveLeft :: (b -> a -> a) -> (a -> b -> b) -> Z a b -> Z a b
moveLeft listF currentF (Z (x:xs, c, ys)) = Z (xs, g x c, ((f c x):ys))
moveRight :: (b -> a -> a) -> (a -> b -> b) -> Z a b -> Z a b
moveRight listF currentF (Z (xs, c, y:ys)) = Z (((f c y):xs), g y c, ys)
ここでlistF
は、リスト要素と現在の要素を左または右のリスト要素に変換します。currentF
現在の要素とリスト要素を現在の要素に変換します。
現在のタイプとリストタイプの両方が等しい場合、移動は簡単です。
moveLeftSameType :: Z a a -> Z a a
moveLeftSameType = moveLeft const const
そして、すべてが期待どおりに機能します。
私が今やりたいのは、上記のアイデアを一般化して、与えられた(たとえば、)の関数listF
と関数を実装するだけで、正しいことを自動的に実行することです。これを行う正しい方法は何でしょうか?currentF
Z a b
a :: Char
b :: Int
moveLeft
moveRight
述べる
私はこのようなクラスを実装しようとしました:
class CPos a where
listF :: c -> d -> d
currentF :: d -> c -> c
moveLeft :: a -> a
moveRight :: a -> a
とmoveLeft/Right
の観点から実装されてlistF
いcurrentF
ますが、これは失敗します
The class method `listF' mentions none of the type variables of the class CPos a
備考2
上記の考え方について私が一般的に気に入らないのは、任意の機能listF
を許可しているという事実でありcurrentF
、保証することは不可能です
moveLeft . moveRight = id
(ジッパーがリスト内にある場合、境界線ではこれはとにかく保持されません)。これを実施するためのヒントはありますか?