1

在我的递归列表转换中,重叠实例的优先级没有按预期进行。

我正在尝试创建一个对任意深度的嵌套列表进行操作的转置函数。目标是有两个函数,一个可以将“最高维度”向下转换为“最低维度”,即维度为 [a, b, c] 的嵌套列表将转换为维度为 [ b, c, a] 和一个相反的,[a, b, c] 到 [c, a, b]。

{-# LANGUAGE FlexibleContexts, FlexibleInstances #-}
module Transpose where
import Data.List

class DeepTranspose a where
    deepTransposeDown :: a -> a
    deepTransposeUp   :: a -> a

instance {-# OVERLAPPING #-} (DeepTranspose a) => DeepTranspose [[a]] where
    deepTransposeDown = map deepTransposeDown.transpose
    deepTransposeUp   = transpose.map deepTransposeUp

instance {-# OVERLAPPABLE #-} DeepTranspose a where
    deepTransposeDown = id
    deepTransposeUp   = id

我的意图是第一个实例应用于所有嵌套列表,第二个实例应用于其他所有内容。

以下是一些测试示例,“ref”表示函数的预期行为


a = [[1,2],[3,4]] :: [[Int]]
b = [[[1,2],[3,4]],[[5,6],[7,8]]] :: [[[Int]]]
c = [[[[1,2],[3,4]],[[5,6],[7,8]]],[[[9,10],[11,12]],[[13,14],[15,16]]]] :: [[[[Int]]]]

ref1a = transpose a
test1a = deepTransposeDown a
ref1b = map transpose.transpose $ b
test1b = deepTransposeDown b
ref1c = map (map transpose.transpose).transpose $ c
test1c = deepTransposeDown c

ref2a = transpose a
test2a = deepTransposeUp a
ref2b = transpose.map transpose $ b
test2b = deepTransposeUp b
ref2c = transpose.map (transpose.map transpose) $ c
test2c = deepTransposeUp c

然而,参考和测试的结果是不同的,例如:

>>>c
[[[[1,2],[3,4]],[[5,6],[7,8]]],[[[9,10],[11,12]],[[13,14],[15,16]]]]
>>>ref1c
[[[[1,9],[2,10]],[[3,11],[4,12]]],[[[5,13],[6,14]],[[7,15],[8,16]]]]
>>>test1c
[[[[1,2],[3,4]],[[9,10],[11,12]]],[[[5,6],[7,8]],[[13,14],[15,16]]]]

我没有太多使用重叠实例的经验,所以我不确定如何选择实例。对我来说,似乎转置只发生在第一个“层”中,之后使用第二个实例(id)。这有效地把它变成了正常的转置,这不是很有趣。

4

1 回答 1

0

我不完全明白发生了什么,但你需要

instance {-# OVERLAPPING #-} (DeepTranspose [a]) => DeepTranspose [[a]] where
                                         -- ^^^ --

这是因为在您的实例中map deepTransposeDown.transpose需要DeepTranspose [a]. 如果您只需要DeepTranspose a,则不足以满足所需的约束,因此它会退回到id实例(即使a=[[Int]])。

于 2019-08-20T12:45:16.483 回答