2016-05-29 2 views
1

При попытке компиляции следующего кода с GHC 7.10.3, он бросает «Перекрытие Инстансы» ошибка у меня:Неясная почему экземпляры перекрывающихся

{-# LANGUAGE DataKinds   #-} 
{-# LANGUAGE FlexibleInstances #-} 
{-# LANGUAGE GADTs    #-} 
{-# LANGUAGE KindSignatures #-} 
{-# LANGUAGE TypeOperators  #-} 

module Main where 

class Bar a where 
    bar :: Foo a 

-- Instance #1 
instance Bar '[a] where 
    bar = C1 

-- Instance #2 
instance (Bar as) => Bar (a ': as) where 
    bar = C2 bar 

data Foo :: [*] -> * where 
    C1 :: Foo '[a] 
    C2 :: Foo as -> Foo (a ': as) 

main :: IO() 
main = undefined 

foobar :: Foo '[Int] 
foobar = bar 

28 col 10 error: Overlapping instances for Bar '[Int] arising from a use of ‘bar’

Matching instances:

instance Bar '[a] -- Defined at test.hs:13:10

instance Bar as => Bar (a : as) -- Defined at test.hs:17:10

In the expression: bar

In an equation for ‘foobar’: foobar = bar

Очевидно '[Int] является экземпляром Bar через #1. Теперь я удивлен, потому что (из моего понимания ситутации) '[Int] = (Int ': '[]) не может быть экземпляром Bar через #2, так как '[] сам по себе не является экземпляром Bar (что необходимо). У меня смутные воспоминания об ограничениях на instanciation, которые не были такими, как я думал, и я подозреваю, что проблема здесь в ... (Bar as) => ..., хотя я не могу быть уверен. Любая помощь оценивается.

+0

Любой 'Bar (a ': as)' также будет 'Bar' [a]', no? – user2297560

+0

@ user2297560 Нет, анализ в вопросе верен в этом вопросе: только когда 'as ~ []' '' a ': as' и '' [a]' то же самое. –

+0

@ Даниэль Вагнер А, я вижу. Благодарю. Этот тип типа уровня все еще немного волшебный для меня. – user2297560

ответ

2

Chris Done написал на сообщение в блоге об этом:

http://chrisdone.com/posts/haskell-constraint-trick

Его делает это наблюдение:

The constraints of an instance don’t have anything to do with deciding whether an instance is picked from the list of instances available. Constraints only apply after GHC has already decided it’s going with this instance.

Так себе ограничение присутствует в:

instance Bar as => Bar (a ': as) 

Безразлично 'исключить GHC из сопоставления с '[Int].

+0

На самом деле я до сих пор не могу заставить его работать. Я получаю ту же ошибку с 'instance (as ~ (a1 ': a2': more), Bar as) => Bar (a '': as), где '. Я бы ожидал, что 'as ~ (a ': b': cs)' будет соответствовать только спискам из двух или более элементов, что (по-прежнему) не относится к '' [Int] '. –

+0

Нет - ответ заключается в том, что экземпляры перекрываются. Я просто процитировал статью в блоге, чтобы указать, что ограничения не влияют на разрешение экземпляра. – ErikR

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