2016-06-11 72 views
1

我試圖創建一個返回惹巴形狀的可變參數函數:Typeclass實例將Int轉換爲Num a?

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

回答

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或之後的版本中有任何其他的實例,所以編譯器可以提前提交給函數實例。