2014-10-10 4 views
0

불완전 추론에 작동하지 않습니다 컴파일 : 당신은 다음과 같은 오류가타입 클래스, 큐, 목록에 대한 인스턴스와 다음 하스켈 프로그램을 컴파일하려고 인해 GHC 7.8

{-# LANGUAGE MultiParamTypeClasses #-} 
{-# LANGUAGE FlexibleInstances #-} 

import qualified Data.List as L 

class Queue c e where 
    new  :: c 
    insert :: e -> c -> c 
    extract :: c -> (e, c) 
    empty :: c -> Bool 

instance Queue [e] e where 
    new   = [] 
    insert   = (:) 
    extract (x:xs) = (x,xs) 
    empty   = L.null 

toList :: Queue c e => c -> [e] 
toList queue | empty queue = [] 
toList queue = let (first,rest) = extract queue in first : toList rest 

main = print (new ([] :: [Int])) 

:

[1 of 1] Compiling Main    (afff.hs, afff.o) 

afff.hs:19:16: 
    Could not deduce (Queue c e1) arising from a use of ‘empty’ 
    from the context (Queue c e) 
     bound by the type signature for toList :: Queue c e => c -> [e] 
     at afff.hs:18:11-31 
    The type variable ‘e1’ is ambiguous 
    Relevant bindings include 
     queue :: c (bound at afff.hs:19:8) 
     toList :: c -> [e] (bound at afff.hs:19:1) 
    Note: there is a potential instance available: 
     instance Queue [e] e -- Defined at afff.hs:12:10 
    In the expression: empty queue 
    In a stmt of a pattern guard for 
        an equation for ‘toList’: 
     empty queue 
    In an equation for ‘toList’: toList queue | empty queue = [] 

afff.hs:22:8: 
    No instance for (Show a0) arising from a use of ‘print’ 
    The type variable ‘a0’ is ambiguous 
    Note: there are several potential instances: 
     instance Show Double -- Defined in ‘GHC.Float’ 
     instance Show Float -- Defined in ‘GHC.Float’ 
     instance (Integral a, Show a) => Show (GHC.Real.Ratio a) 
     -- Defined in ‘GHC.Real’ 
     ...plus 24 others 
    In the expression: print (new ([] :: [Int])) 
    In an equation for ‘main’: main = print (new ([] :: [Int])) 

afff.hs:22:15: 
    No instance for (Queue ([Int] -> a0) e0) 
     arising from a use of ‘new’ 
    In the first argument of ‘print’, namely ‘(new ([] :: [Int]))’ 
    In the expression: print (new ([] :: [Int])) 
    In an equation for ‘main’: main = print (new ([] :: [Int])) 

shell returned 1 

왜 GHC가 "e1 = Int"를 추론 할 수없는 이유가 무엇입니까?

답변

4

분명히 (e1 ~ Int) 인 경우가 아니기 때문에 (c ~ [Int])입니다. GTC는 MPTC를 사용하기 위해 모든 유형 매개 변수를 알아야합니다. empty 유형은 유형 매개 변수 중 하나만 참조하므로 결코 사용될 수 없습니다.

저는 GHC가이 클래스 정의를 즉시 거부하지 않아도된다는 의견을 확실히 밝혔습니다. 사용하는 것이 명백히 불가능하므로 사용하지 않을 때까지 기다리지 않는 이유는 무엇입니까?

당신이 좋아하는 유형 매개 변수 c과 일치하는 인스턴스가 하나 뿐이라고 생각할 수도 있지만 그렇지 않은 것 같습니다. GHC는 수업 해결 중에 어떤 사례가 보일지 신경 쓰지 않습니다. 그것은 어떤 클래스가 존재해야 하는지를 결정한 다음 그것을 검사합니다.

귀하의 경우에는 "내가 무엇이 필요한지 알고 있습니다. 그러나 ... 필요한 것이 무엇인지 실감하지 못했습니다. 사용하고자하는 인스턴스가 무엇인지 말할 수 없습니다." 제 말대로,이 문제는 클래스 자체의 정의에서 명백합니다.

이 문제를 해결하는 가장 직접적인 방법은이 같은 함수 적 종속성, 함께 :

class Queue c e | c -> e where 
    new  :: c 
    insert :: e -> c -> c 
    extract :: c -> (e, c) 
    empty :: c -> Bool 

는 사용할 FunctionalDependencies 언어 확장을 필요로 그. 형식 e이 형식 c에 의해 고유하게 결정된다는 것을 컴파일러에 지정합니다. 즉, 동일한 유형 인 c을 가지지 만 다른 유형은 e 인 한 쌍의 인스턴스를 거부하고 사용하려는 인스턴스를 선택하기에 충분한 정보가있는 유형이 c 인 경우이를 가정합니다.

+0

아, 그건 의미가 있습니다, 감사합니다! 좋은 대답. – MaiaVictor