重複するインスタンスは、再帰リスト変換で意図したとおりに優先されません。
任意の深さのネストされたリストで動作する転置関数を作成しようとしています。目標は 2 つの関数を用意することです。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
私の意図は、最初のインスタンスがすべてのネストされたリストに適用され、2 番目のインスタンスが他のすべてに適用されることです。
以下はテストの例です。「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]]]]
重複するインスタンスを使用した経験があまりないため、インスタンスの選択方法がわかりません。私には、転置は最初の「レイヤー」でのみ発生し、その後で 2 番目のインスタンス (id) が使用されるように見えます。これにより、効果的に通常のトランスポーズに変わりますが、これはあまり興味深いものではありません。