-XAllowAmbiguousTypes는 언제 적절한가요?


212

최근 에의 정의와 관련하여 syntactic-2.0 에 대한 질문을 게시했습니다 . GHC 7.6 에서이 작업을 수행했습니다 .share

{-# LANGUAGE GADTs, TypeOperators, FlexibleContexts #-}

import Data.Syntactic
import Data.Syntactic.Sugar.BindingT

data Let a where
    Let :: Let (a :-> (a -> b) :-> Full b)

share :: (Let :<: sup,
          sup ~ Domain b, sup ~ Domain a,
          Syntactic a, Syntactic b,
          Syntactic (a -> b),
          SyntacticN (a -> (a -> b) -> b) 
                     fi)
           => a -> (a -> b) -> b
share = sugarSym Let

그러나 GHC 7.8은 -XAllowAmbiguousTypes해당 서명으로 컴파일 하려고 합니다. 다른 방법 fi으로

(ASTF sup (Internal a) -> AST sup ((Internal a) :-> Full (Internal b)) -> ASTF sup (Internal b))

이는 Fundep에 의해 암시 된 유형입니다 SyntacticN. 이렇게하면 확장을 피할 수 있습니다. 물론 이것은

  • 이미 큰 서명에 추가 할 수있는 매우 긴 유형
  • 수동으로 유도하기에 귀찮음
  • Fundep로 인해 불필요

내 질문은 :

  1. 이 사용이 허용 -XAllowAmbiguousTypes됩니까?
  2. 일반적으로이 확장은 언제 사용해야합니까? 여기에 대한 답변 은 "거의 좋은 아이디어는 아닙니다"라고 제안합니다.
  3. 문서를 읽었지만 제약 조건이 모호한 지 여부를 결정하는 데 여전히 문제가 있습니다. 특히, Data.Syntactic.Sugar에서이 기능을 고려하십시오.

    sugarSym :: (sub :<: AST sup, ApplySym sig fi sup, SyntacticN f fi) 
             => sub sig -> f
    sugarSym = sugarN . appSym

    나에게 fi(그리고 아마도 sup) 모호 해야하는 것처럼 보이지만 확장명없이 컴파일됩니다. 왜 sugarSym모호하지 share않은가? 이후 share의 응용 프로그램 sugarSymshare제약 조건은 모든 직선에서 온 sugarSym.


4
모호한 유형 변수를 포함하거나 포함하지 않는에 대해 유추 된 유형을 사용할 수없는 이유 sugarSym Let(SyntacticN f (ASTF sup a -> ASTF sup (a -> b) -> ASTF sup b), Let :<: sup) => f있습니까?
kosmikus

3
@ kosmikus Sorrt 응답하는 데 너무 오래 걸렸습니다. 이 코드 에 대한 추론 서명 컴파일되지 않습니다 share,하지만 하지 질문에서 언급 한 서명 중 하나를 사용하는 경우 컴파일. 당신은 또한 이전 게시물
crockeea

3
정의되지 않은 행동은 아마도 가장 적절한 용어는 아닙니다. 하나의 프로그램을 기반으로 이해하는 것은 어렵습니다. 문제는 결정 성과 GHCI가 프로그램의 유형을 증명할 수 없다는 것입니다. 이 주제에만 관심을 가질만한 긴 토론이 있습니다. haskell.org/pipermail/haskell-cafe/2008-April/041397.html
BlamKiwi

6
(3)의 경우 SyntacticN (즉, f-»fi) 및 ApplySym (특히 fi-> sig, sup)의 정의에서 기능적 종속성으로 인해 해당 유형이 모호하지 않습니다. 그에서, 당신이 얻을 f혼자 충분 완전히 명확하다 sig, fi하고 sup.
user2141650

3
@ user2141650 답장하는 데 시간이 오래 걸렸습니다. 당신의 fundep 말을하는지 SyntacticN차종 fi에 명확한를 sugarSym하지만, 왜 true를 동일하지 않습니다 fishare?
crockeea 2016 년

답변:


12

서명에 sugarSym정확한 유형 이름 을 사용하는 게시 된 구문 버전이 표시되지 않으므로 커밋 8cfd02 ^에서 개발 브랜치를 사용합니다.

그렇다면 왜 GHC가 fi타입 시그너처에 대해 불평 하지만 왜 시그니처에 대해 불평하지 sugarSym않습니까? 연결 한 문서는 제약 조건이 기능적 종속성을 사용하여 다른 모호하지 않은 유형에서 다른 모호하지 않은 유형을 유추하지 않는 한 유형이 제약 조건의 오른쪽에 나타나지 않으면 모호하다는 것을 설명합니다. 두 함수의 컨텍스트를 비교하고 함수 종속성을 찾으십시오.

class ApplySym sig f sym | sig sym -> f, f -> sig sym
class SyntacticN f internal | f -> internal

sugarSym :: ( sub :<: AST sup
            , ApplySym sig fi sup
            , SyntacticN f fi
            ) 
         => sub sig -> f

share :: ( Let :<: sup
         , sup ~ Domain b
         , sup ~ Domain a
         , Syntactic a
         , Syntactic b
         , Syntactic (a -> b)
         , SyntacticN (a -> (a -> b) -> b) fi
         )
      => a -> (a -> b) -> b

그래서 대한 sugarSym비 모호한 유형은 sub, sigf, 그에서 우리는 즉, 문맥에서 사용되는 모든 다른 유형을 명확하게하기 위해 함수 종속을 수행 할 수 있어야 sup하고 fi. 실제로, f -> internal기능적 의존성 SyntacticN은 우리 f를 명확하게하기 위해 사용하고 fi, 그 후에 f -> sig sym기능적으로 의존하는 것은 ApplySym명확하게 명확하게 fi하기 위해 새로 명확 하게 sup(그리고 sig이미 모호하지 않은) 사용합니다. 따라서 확장이 sugarSym필요없는 이유를 설명합니다 AllowAmbiguousTypes.

이제 보자 sugar. 가장 먼저하는 일의 I 통지 컴파일러가된다는 점이다 없는 경우 중복에 대해 다소 모호한 유형에 대해 불평하지만 :

Overlapping instances for SyntacticN b fi
  arising from the ambiguity check for share
Matching givens (or their superclasses):
  (SyntacticN (a -> (a -> b) -> b) fi1)
Matching instances:
  instance [overlap ok] (Syntactic f, Domain f ~ sym,
                         fi ~ AST sym (Full (Internal f))) =>
                        SyntacticN f fi
    -- Defined in ‘Data.Syntactic.Sugar’
  instance [overlap ok] (Syntactic a, Domain a ~ sym,
                         ia ~ Internal a, SyntacticN f fi) =>
                        SyntacticN (a -> f) (AST sym (Full ia) -> fi)
    -- Defined in ‘Data.Syntactic.Sugar’
(The choice depends on the instantiation of b, fi’)
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes

따라서이 권리를 읽고 있다면 GHC가 유형이 모호하다고 생각하는 것이 아니라 유형이 모호한 지 여부를 확인하는 동안 GHC가 다른 별도의 문제를 겪었다는 것입니다. 그런 다음 GHC에 모호성 검사를 수행하지 말라고 지시하면 별도의 문제가 발생하지 않았을 것입니다. 이것은 AllowAmbiguousTypes를 활성화하면 코드를 컴파일 할 수있는 이유를 설명합니다.

그러나 겹치는 인스턴스의 문제는 남아 있습니다. GHC ( SyntacticN f fiSyntacticN (a -> f) ...)로 나열된 두 인스턴스 는 서로 겹칩니다. 이상하게도, 첫 번째 인스턴스는 다른 인스턴스와 겹치는 것처럼 보입니다. 그리고 무슨 [overlap ok]뜻입니까?

Syntactic이 OverlappingInstances로 컴파일 된 것 같습니다. 그리고 실제로 코드를 살펴보십시오 .

조금 실험 해보면, GHC가 하나가 다른 것보다 더 일반적이라는 것이 분명 할 때 겹치는 경우에 괜찮은 것 같습니다.

{-# LANGUAGE FlexibleInstances, OverlappingInstances #-}

class Foo a where
  whichOne :: a -> String

instance Foo a where
  whichOne _ = "a"

instance Foo [a] where
  whichOne _ = "[a]"

-- |
-- >>> main
-- [a]
main :: IO ()
main = putStrLn $ whichOne (undefined :: [Int])

그러나 GHC는 다른 인스턴스보다 명확하게 더 잘 맞지 않을 때 겹치는 인스턴스에는 적합하지 않습니다.

{-# LANGUAGE FlexibleInstances, OverlappingInstances #-}

class Foo a where
  whichOne :: a -> String

instance Foo (f Int) where  -- this is the line which changed
  whichOne _ = "f Int"

instance Foo [a] where
  whichOne _ = "[a]"

-- |
-- >>> main
-- Error: Overlapping instances for Foo [Int]
main :: IO ()
main = putStrLn $ whichOne (undefined :: [Int])

귀하의 유형 서명 사용 SyntacticN (a -> (a -> b) -> b) fi, 어느 쪽도 아니 SyntacticN f fi도는 SyntacticN (a -> f) (AST sym (Full ia) -> fi)다른 것보다 더 적합하다. 유형 서명의 해당 부분을 SyntacticN a fi또는로 변경 SyntacticN (a -> (a -> b) -> b) (AST sym (Full ia) -> fi)하면 GHC는 더 이상 중복에 대해 불평하지 않습니다.

내가 당신이라면, 가능한 두 인스턴스의 정의를 보고 그 두 구현 중 하나가 당신이 원하는 것인지 결정합니다.


2

AllowAmbiguousTypes와 함께 사용하기에 매우 편리 하다는 것을 알았습니다 TypeApplications. GHC.TypeLits 의 함수 natVal :: forall n proxy . KnownNat n => proxy n -> Integer를 고려하십시오 .

이 기능을 사용하려면을 쓸 수 natVal (Proxy::Proxy5)있습니다. 또 다른 스타일을 사용하는 것입니다 TypeApplications: natVal @5 Proxy. 의 유형은 Proxy유형 응용 프로그램에 의해 유추되며 호출 할 때마다 작성해야합니다 natVal. 따라서 다음을 활성화 AmbiguousTypes하고 쓸 수 있습니다 .

{-# Language AllowAmbiguousTypes, ScopedTypeVariables, TypeApplications #-}

ambiguousNatVal :: forall n . (KnownNat n) => Integer
ambiguousNatVal = natVal @n Proxy

five = ambiguousNatVal @5 -- no `Proxy ` needed!

그러나 일단 모호해지면 다시 돌아갈 수 없습니다 !

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.