İmzası sugarSym
tam olarak bu tür adları kullanan herhangi bir sözdizim yayınlanmış sürümünü görmüyorum , bu yüzden hala bu adları kullanan son sürüm olan 8cfd02 ^ 'de geliştirme dalını kullanacağım .
Öyleyse, GHC neden fi
sizin tip imzanızdan şikayet ediyor, ancak neden imzanızdan şikayet ediyor sugarSym
? Bağlandığınız belgeler, bir türün, diğer belirsiz olmayan türlerden başka türlü belirsiz türler çıkarmak için işlevsel bağımlılıklar kullanmadığı sürece, kısıtlamanın sağında görünmüyorsa belirsiz olduğunu açıklar. Şimdi iki fonksiyonun bağlamlarını karşılaştıralım ve fonksiyonel bağımlılıkları araştıralım.
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
Yani için sugarSym
, olmayan belirsiz türleridir sub
, sig
ve f
, ve olanlardan biz yani bağlamda kullanılan tüm diğer türleri belirsizliği amacıyla fonksiyonel bağımlılıkları takip etmek gerekir sup
ve fi
. Ve aslında, bizim f -> internal
fonksiyonel bağımlılık SyntacticN
bizim f
anlamını belirsizleştirmek için kullanır fi
, ve daha sonra kullanımdaki f -> sig sym
fonksiyonel bağımlılık ApplySym
bizim de belirsizleştirmek fi
için yeni de ayrışmış sup
(ve sig
zaten belirsiz olmayan) kullanır. Bu da neden uzantı sugarSym
gerektirmediğini açıklıyor AllowAmbiguousTypes
.
Şimdi bakalım sugar
. Ilk şey gözüme derleyici olmasıdır değil örneklerini çakışması konusunda oldukça belirsiz bir türü hakkında şikayetçi ama:
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
Bu yüzden doğru okuyorsam, GHC, türlerinizin belirsiz olduğunu düşünmez, aksine, türlerinizin belirsiz olup olmadığını kontrol ederken, GHC farklı, ayrı bir sorunla karşılaştı. Daha sonra size GHC'ye belirsizlik kontrolü yapmamasını söylerseniz, bunun ayrı bir sorunla karşılaşmayacağını söyler. Bu, AllowAmbiguousTypes'i etkinleştirmenin neden kodunuzun derlenmesine izin verdiğini açıklar.
Ancak, örtüşen örneklerle ilgili sorun devam etmektedir. GHC ( SyntacticN f fi
ve SyntacticN (a -> f) ...
) tarafından listelenen iki örnek birbiriyle çakışır. Garip bir şekilde, bunlardan birincisi şüpheli olan başka bir örnekle çakışmalıdır. Peki ne [overlap ok]
demek?
Syntactic'in OverlappingInstances ile derlendiğinden şüpheleniyorum. Ve koda bakarak , gerçekten de öyle.
Biraz deneme yaparak, birinin diğerinden kesinlikle daha genel olduğu açık olduğunda GHC örtüşen örneklerle iyi görünüyor:
{-# 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])
Ancak GHC, ikisi de açıkça diğerinden daha iyi olmadığında örtüşen örneklerle iyi değildir:
{-# 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])
Kişisel tipi imza kullandığı SyntacticN (a -> (a -> b) -> b) fi
ve ne SyntacticN f fi
de SyntacticN (a -> f) (AST sym (Full ia) -> fi)
diğerinden daha iyi bir seçimdir. Tür imzanızın bu kısmını SyntacticN a fi
veya olarak değiştirirsem SyntacticN (a -> (a -> b) -> b) (AST sym (Full ia) -> fi)
, GHC artık çakışmadan şikayet etmez.
Ben siz olsaydım , bu iki olası örneğin tanımına bakar ve bu iki uygulamadan birinin istediğiniz biri olup olmadığını tespit ederdim .
sugarSym Let
, sadece türünü kullanamamanızın bir nedeni var mı(SyntacticN f (ASTF sup a -> ASTF sup (a -> b) -> ASTF sup b), Let :<: sup) => f
?