如何为元组和打包类型创建 ListIsomorphic 实例?

How to create ListIsomorphic instances for tuples and packed types?

抱歉,这是同系列的另一个话题。我有一个与列表同构的事物的类型类:

class ListIsomorphic l where
    type Elem l a :: Constraint
    type Elem l a = ()

    toList    :: l a -> [a]
    fromList  :: [a] -> l a

有两种情况我无法创建实例;单类型元组和将多个元素打包在一个值中的类型。

type Tuple2 a   = (a,a)
newtype Pixel a = Pixel a

在这种情况下,Pixel 通常持有一个 Word32,其中包含 4 个元素,这些元素是通过按位运算提取的:

red (Pixel pixel)   = pixel .&. 0x000000FF
green (Pixel pixel) = shiftR (pixel .&. 0x0000FF00) 8
blue (Pixel pixel)  = shiftR (pixel .&. 0x00FF0000) 16
alpha (Pixel pixel) = shiftR (pixel .&. 0xFF000000) 24

虽然这两种情况都不是列表的同构(它们是固定长度的),但拥有一个实例会很有用,但我不确定如何向类型系统证明这一点。为元组编写实例:

type Tuple2 a = (a,a)
instance ListIsomorphic Tuple2 where
    fromList [a,b] = (a,b)
    toList   (a,b) = [a,b]

我得到:

Type synonym ‘Tuple2’ should have 1 argument, but has been given none

正在为 Pixel 编写实例:

instance ListIsomorphic Pixel where
    type Elem Pixel_ a = Word32
    fromList [r,g,b,a] = rgba r g b a
    toList pixel       = [red pixel, green pixel, blue pixel, alpha pixel]

我得到:

Expected a constraint, but ‘Word32’ has kind ‘*’

当然,我没想到会这样,但就是说我不知道​​怎么写。

约束族

type Elem l a :: Constraint
type Elem l a = ()

允许您限制那​​些容器中可能包含的类型。在 Tuple2 或列表本身的情况下,这根本没有必要,因为它们可以包含 any 类型的元素。
在这种情况下,例如Storable 个向量,您需要可以实际存储在 C 数组中的原始类型。
Pixel的情况下,只能存储一种类型,即Word32。这意味着你需要一个等式约束:

instance ListIsomorphic Pixel where
    type Elem Pixel a = a~Word32