1

我正在玩弄拉链,其中当前元素可以具有与左右列表不同的类型:

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

一切都按预期工作,很好!

我现在想做的是概括上述想法,这样只需为给定的(比如, )实现listFandcurrentF函数,并自动做正确的事情。这样做的正确方法是什么?Z a ba :: Charb :: IntmoveLeftmoveRight

评论

我试图实现这样的类:

class CPos a where
    listF :: c -> d -> d
    currentF :: d -> c -> c
    moveLeft :: a -> a
    moveRight :: a -> a

wheremoveLeft/Right是根据listFand实现的currentF,但这失败了

The class method `listF' mentions none of the type variables of the class CPos a

备注 2

我一般不喜欢上述想法的一点是允许任意函数listF并且currentF无法保证

moveLeft . moveRight = id

(如果拉链在列表中,则在边框上无论如何都不存在)。执行此操作的任何提示?

4

1 回答 1

1

这是一个解决方案。

class CPos a b where
    listF :: b -> a -> a
    currentF :: a -> b -> b
    moveLeft :: Z a b -> Z a b
    moveLeft (Z (x:xs, c, ys)) = Z (xs, currentF x c, ((listF c x):ys))
    moveRight :: Z a b -> Z a b
    moveRight (Z (xs, c, y:ys)) = Z (((listF c y):xs), currentF y c, ys)

我不认为你可以强制执行moveLeft . moveRight = id。我的意思是不能保证两个函数相等。您能做的最好的事情就是编写quickcheck测试用例来保证相同。

于 2012-09-14T16:28:40.793 回答