私は最近share
の定義に関して question について syntactic-2. を投稿しました。私はこれをGHC 7.6で動作させました:
{-# 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))
これは、SyntacticN
のFundepによって暗示されるタイプです。これにより、拡張を回避できます。もちろんこれは
私の質問は:
-XAllowAmbiguousTypes
?ドキュメント を読みましたが、制約があいまいであるかどうかを判断するのにまだ苦労しています。具体的には、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
はsugarSym
のアプリケーションであるため、share
制約はすべてsugarSym
から直接取得されます。
sugarSym
のシグニチャーがこれらの正確なタイプ名を使用する構文の公開バージョンは表示されないため、 コミット8cfd02 ^の開発ブランチ を使用します。それらの名前を使用しました。
それでは、なぜGHCはfi
についてではなく、あなたのタイプ署名のsugarSym
について文句を言うのでしょうか?リンクしたドキュメントでは、制約が機能的な依存関係を使用して他の曖昧でないタイプから曖昧なタイプを推測しない限り、制約の右側に表示されない場合、タイプは曖昧であると説明されています。それでは、2つの関数のコンテキストを比較して、機能的な依存関係を探しましょう。
_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
、sig
、およびf
であり、それらから、他のすべてを明確にするために機能的な依存関係に従うことができるはずですコンテキストで使用されるタイプ、つまりsup
およびfi
。そして実際、SyntacticN
の_f -> internal
_機能依存性はf
を使用してfi
を明確にし、その後ApplySym
の_f -> sig sym
_機能依存性はfi
(およびsup
、これは既にあいまいではありませんでした)を明確にするために、新しく明確化されたsig
。それで、sugarSym
がAllowAmbiguousTypes
拡張を必要としない理由を説明します。
sugar
を見てみましょう。私が最初に気づくのは、コンパイラがnotあいまいな型ではなく、インスタンスの重複について不平を言っていることです:
_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によってリストされた2つのインスタンス(_SyntacticN f fi
_およびSyntacticN (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つの可能なインスタンスの定義 を見て、これら2つの実装のどちらかがあなたが望むものかどうかを判断します。