2013-10-01 3 views
2

Вот простой polyvariadic функция, смоделирован Text.Printf.printf:Зачем нужна эта многовариантная функция для аннотации типа?

{-# LANGUAGE FlexibleInstances #-} 

sumOf :: SumType r => r 
sumOf = sum' [] 

class SumType t where 
    sum' :: [Integer] -> t 

instance SumType (IO a) where 
    sum' args = print (sum args) >> return undefined 

instance (SumArg a, SumType r) => SumType (a -> r) where 
    sum' args = \a -> sum' (toSumArg a : args) 

class SumArg a where 
    toSumArg :: a -> Integer 

instance SumArg Integer where 
    toSumArg = id 

Это хорошо в GHCI работает без каких-либо аннотаций типа:

ghci> sumOf 1 2 3 
6 

Однако, когда я удалить SumArg a ограничение ...

instance SumType r => SumType (Integer -> r) where 
    sum' args = \a -> sum' (toSumArg a : args) 

... не удается:

ghci> sumOf 1 2 3 

<interactive>:903:7: 
    No instance for (Num a0) arising from the literal `3' 
    The type variable `a0' is ambiguous 
    Possible fix: add a type signature that fixes these type variable(s) 
    Note: there are several potential instances: 
     instance Num Double -- Defined in `GHC.Float' 
     instance Num Float -- Defined in `GHC.Float' 
     instance Integral a => Num (GHC.Real.Ratio a) 
     ...plus 14 others 
    In the third argument of `sumOf', namely `3' 
    In the expression: sumOf 1 2 3 
    In an equation for `it': it = sumOf 1 2 3 

Почему?

(Честно говоря, я больше запутывается о том, что первая версия не необходимости набирать аннотации своих аргументов.)

+0

Первая версия не требует аннотации типа из-за [расширенный недобросовестный] (http://www.haskell.org/ghc/ документы/7.6.2/html/users_guide/интерактивно-evaluation.html # продлен по умолчанию-правила). –

ответ

4

Это потому, что 1 имеет тип Num n => n. Поэтому при поиске подходящего экземпляра для sumOf 1 он не будет соответствовать Integer -> r. Но a -> r всегда совпадает, поэтому он находит совпадение в первом случае, а в конце a по умолчанию - Integer. Так что я бы ожидать, что это работает, где a ~ Integer силы a стать Integer:

instance (a ~ Integer, SumType r) => SumType (a -> r) where 
    sum' args = \a -> sum' (toSumArg a : args) 
+2

Ой, я забыл, что ограничения не влияют на процесс сопоставления. Благодаря! – Artyom

Смежные вопросы