我尝试创建一个返回Repa形状的可变函数:
class Indexable r where
idx :: [Int] -> r
instance Indexable Int where
idx [x] = x
instance (Indexable b) => Indexable (Int :. b) where
idx (x:xx) = x :. (idx xx)
instance (Indexable a) => Indexable (Z :. a) where
idx xs = Z :. (idx xs)
instance (Indexable r) => Indexable (Int -> r) where
idx xs = \x -> idx (x:xs)
有效:
> fromListUnboxed (idx [] (3 :: Int)) [1..3] :: Array U DIM1 Int
AUnboxed (Z :. 3) [1,2,3]
但我必须明确使用3 :: Int
而不是3
,尽管我的实例明确使用Int
。以下让我困惑:
> :t idx [] 3
idx [] 3 :: (Num a, Indexable (a -> t)) => t
我认为实例中的类型签名会强制数字为Int
,但它会变成Num a
。为什么?如何让编译器识别出所有数字都是Int
s?
答案 0 :(得分:5)
类型类 open :稍后,可能在另一个模块中,您可以定义另一个实例。编译器不能依赖你不这样做,所以它不能提交你到目前为止定义的实例。
您可以为您的函数实例尝试此操作,而不是:
instance (Indexable r, a ~ Int) => Indexable (a -> r) where
idx xs = \x -> idx (x:xs)
与Int -> r
的实例不同,此实例涵盖整个函数空间a -> r
,但需要a ~ Int
。这告诉编译器以后不能有任何其他形式的Char -> r
或类似的实例,因此允许编译器尽早提交给函数实例。