2016-06-13 11 views
8

는 내가 원하는 것은 이런 식으로 뭔가를 작성하는 것입니다Control.Arrow : "let (a, b) = (first, second)"가 실패하는 이유는 무엇입니까? 나는 심지어이 쓸 수 있다는 것을 발견</p> <p><code>let (a,b) = if *condition* then (first, second) else (second, first)</code></p> <p>:

let (a,b) = (first,second)

이 오류와 함께 실패합니다

<interactive>:7:5:                               
Could not deduce (Arrow a0)                            
from the context (Arrow a) 
    bound by the inferred type for `a': 
      Arrow a => a b c -> a (b, d) (c, d) 
    at <interactive>:7:5-26 
The type variable `a0' is ambiguous 
When checking that `a' has the inferred type 
    a :: forall (a :: * -> * -> *) b c d. 
     Arrow a => 
     a b c -> a (b, d) (c, d) 
Probable cause: the inferred type is ambiguous 

<interactive>:7:5: 
Could not deduce (Arrow a0) 
from the context (Arrow a) 
    bound by the inferred type for `b': 
      Arrow a => a b c -> a (d, b) (d, c) 
    at <interactive>:7:5-26 
The type variable `a0' is ambiguous 
When checking that `b' has the inferred type 
    b :: forall (a :: * -> * -> *) b c d. 
     Arrow a => 
     a b c -> a (d, b) (d, c) 
Probable cause: the inferred type is ambiguous 
+5

사이먼 페이튼 존스 (지금은 찾기 힘든 데) 메일 링리스트 중 하나에 큰 이메일을이 같은 유형 검사 패턴 바인딩의 미묘한 차이에 대해 설명하는 이. 실제로 Haskell98 보고서가이 문제를 완전히 간과 한 것은 매우 미묘하며,위원회는 Haskell 2010 보고서를 작성하기 전에 패턴 바인딩을 위해 형식 검사가 어떻게 수행되어야하는지에 대해 심도있는 시간을 보냈습니다. 나는 내 앞에서 SPJ의 이메일없이 미묘함을 바로 잡을 자신을 신뢰하지 않는다는 것을 제외하고는 답을 쓸 것입니다. –

+0

짐작할 때, 여기서의 문제는 바인딩의 우변이 유추 된 타입을 얻는다는 것입니다. a1 a2. (for a1, a1 => ..., a2 for a2, a2 ​​=> ...)'와는 반대로 (a1, a2) => (a1 ..., a2 ...) 그래서 forall은 tuple의 out * out으로 옮겨지고 그 쌍의 값 중 하나는 완전히 다형성이 아닙니다. –

답변

2

매우 곧, 당신은 Impredicative 유형을 구성하려고하는 GHC 추론 할 수 없다.

λ Control.Arrow > let (a,b) = (first, second) :: Arrow a => (a b b -> a (b, b) (b, b), a b b -> a (b, b) (b, b)) 
λ Control.Arrow > :t a 
a :: Arrow a => a b b -> a (b, b) (b, b) 
λ Control.Arrow > :t b 
b :: Arrow a => a b b -> a (b, b) (b, b) 

또는

:set -XImpredicativeTypes 
λ Control.Arrow > let (a,b) = (first, second) :: (Arrow a => a b b -> a (b, b) (b, b), Arrow a => a b b -> a (b, b) (b, b)) 
λ Control.Arrow > :t a 
a :: Arrow a => a b b -> a (b, b) (b, b) 
λ Control.Arrow > :t b 
b :: Arrow a => a b b -> a (b, b) (b, b) 

을하지만 당신은 할 수 없습니다 : 당신이 할 수있는

λ Control.Arrow > let (a,b) = (first, second) :: (Arrow a, Arrow a') => (a b b -> a (b, b) (b, b), a' b b -> a' (b, b) (b, b)) 

이 문제를 격리하기 위해이 작품 :

λ Control.Arrow > let p = (first, second) :: (Arrow a, Arrow a') => (a b b -> a (b, b) (b, b), a' b b -> a' (b, b) (b, b)); 
λ Control.Arrow > :t p 
p :: (Arrow a', Arrow a) => 
    (a b b -> a (b, b) (b, b), a' b b -> a' (b, b) (b, b)) 

하지만 그 패턴을 바인딩하려고하면 :

λ Control.Arrow > let (a, b) = p 

오류가 발생합니다. 제약

λ Control.Arrow > :set -XImpredicativeTypes 
λ Control.Arrow > let p = (first, second) :: (Arrow a => a b b -> a (b, b) (b, b), Arrow a => a b b -> a (b, b) (b, b)) 
λ Control.Arrow > let (a, b) = p 

작품으로, 한 쌍 유형의 외부에있는, 그리고 한 쌍의 다른 반쪽에 대한 중복.


간단한 예 :

λ Prelude Data.Monoid > :t (mappend,()) 
(mappend,()) :: Monoid a => (a -> a -> a,()) 
λ Prelude Data.Monoid > let (a, b) = (mappend,()) 

<interactive>:12:5: 
    No instance for (Monoid a0) 
     arising from the ambiguity check for ‘b’ 
    The type variable ‘a0’ is ambiguous 
    When checking that ‘b’ has the inferred type ‘()’ 
    Probable cause: the inferred type is ambiguous 

하나는 제약을 이월해야하지만, 즉 Monoid a =>()이 ambigious 유형, ()의 종류에는 a이 없습니다.


참고 : let (a,b) = ((+), (*))이 작동하는 것 같습니다.나는 아무 생각이 왜, 어떻게 Num 특별히 처리됩니다

λ Prelude Data.Monoid > let x =() :: Num a =>() 
λ Prelude Data.Monoid > :t x 
x ::() 
λ Prelude Data.Monoid > let x =() :: Monoid m =>() 

<interactive>:12:9: 
    No instance for (Monoid m0) 
    ... 
1

monomorphism restriction처럼 보입니다. 이것은 Haskell의 타입 유추의 한계 일 뿐이며 명시 적 타입 서명을 추가하여 해싱 할 수 있습니다.

import Control.Arrow 

foo :: (Arrow a, Arrow a1) => (a b c -> a (b, d) (c, d), a1 b1 c1 -> a1 (d1, b1) (d1, c1)) 
foo = (first, second) 

이 코드는 foo의 형태 서명을 잘 typechecks하지만 당신이 그것을 제거하면 그 "모호한 변수"컴파일 오류를 제공합니다.

BTW, 제가 사용하는 형식 서명은 GHCI에서 :t (first, second)으로 유추 된 것입니다. 동일한 유형을 가지고 (first, second)(second, first)를 원하기 때문에, 당신은 아마 그런 다음 하나, 당신의 주석에보다 구체적인 유형을 사용하는 것이 좋습니다 :

foo :: (Arrow a) => (a b b -> a (b, b) (b, b), a b b -> a (b, b) (b, b)) 
+1

그는 foo = ...가 아니라'(a, b) = ...'를 사용합니다. 이것은 단일 형태 제한이 아닙니다. 그것을 끄고 직접보십시오. 게시 한 코드에 올바른 가져 오기 기능이 없기 때문에이 작업을 수행하지 않았 음을 보증 할 수 있습니다. –

+0

@DanielWagner : 수입에 대해 사과드립니다. 그건 그냥 오타 였고 실제로 실행중인 코드는 맨 위에 올바른 "Control.Arrow"를 가지고있었습니다. – hugomg

+3

그럼에도 불구하고 내가 제기 한 다른 반대 때문에 답변이 잘못되었습니다.'(a, b) = ...'와'foo = ... '는 똑같은 행동을하지 않습니다. –