У меня был умный механизм уровня типов, который работал на GHC 7.6, но не на более поздних версиях. Оглядываясь назад, я не совсем уверен, почему это когда-либо работало, но, тем не менее, я хотел бы как-то вернуть эту функциональность:
{-# LANGUAGE
PolyKinds
, FunctionalDependencies , FlexibleInstances , FlexibleContexts
, OverlappingInstances
, ScopedTypeVariables
, TypeFamilies
, UndecidableInstances
#-}
module M where
import Data.Proxy
-- | A relation between a (maybe-partially-applied) type and that type fully
-- applied.
class Applied t (tab :: *) | t -> tab where
-- | Fully apply a type @t@ with polymorphic arguments, yielding @tab@.
applied :: Proxy t -> Proxy tab
instance Applied (t a) tab=> Applied t tab where
applied _ = applied (Proxy :: Proxy (t a))
instance t ~ tab=> Applied t tab where -- always matches when `t` is kind `*`
applied _ = Proxy :: Proxy tab
Это зависит от библиотеки tagged
в GHC 7.6. Мы можем использовать его как:
$ ghci-7.6.3
Prelude> :l M.hs
[1 of 1] Compiling M ( M.hs, interpreted )
Ok, modules loaded: M.
*M>
*M> :t applied (Proxy :: Proxy Either)
applied (Proxy :: Proxy Either) :: Proxy (Either a a1)
*M> (return $ Right 'a') == applied (Proxy :: Proxy Either)
True
Однако это не компилируется по крайней мере на GHC 7.8.3 или более поздней версии:
$ ghci-7.8.3
GHCi, version 7.8.3: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> :l M.hs
[1 of 1] Compiling M ( M.hs, interpreted )
M.hs:19:10:
Could not deduce (Applied (t a0) tab)
arising from the ambiguity check for an instance declaration
from the context (Applied (t a) tab)
bound by an instance declaration:
Applied (t a) tab => Applied t tab
at M.hs:19:10-42
The type variable ‘a0’ is ambiguous
In the ambiguity check for:
forall (k :: BOX) (k1 :: BOX) (t :: k1 -> k) tab (a :: k1).
Applied (t a) tab =>
Applied t tab
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
In the instance declaration for ‘Applied t tab’
M.hs:19:10:
Illegal instance declaration for ‘Applied t tab’
The liberal coverage condition fails in class ‘Applied’
for functional dependency: ‘t -> tab’
Reason: lhs type ‘t’ does not determine rhs type ‘tab’
In the instance declaration for ‘Applied t tab’
Failed, modules load
Я думаю, что ответ здесь связан, но я пока не понимаю этого предложения.
Возможно, я мог бы обойти это. Единственное место, где я использую этот класс, — это подпись вида:
instance (Foo tab, Applied t tab)=> Bar (Proxy t) where
Это может указывать на то, что я хочу сделать Foo
родо-полиморфным, но это в большой сложной библиотеке, и я не знаю, возможно ли такое изменение.
t :: * ^ n -> *
, что существует экземплярFoo (t a_1 a_2 .. a_n)
, гдеa_i
— переменные разных типов. В этом случае вы можете заменитьApplied (t a) tab
наApplied (t X) tab
, где X — любой тип. Пока X определен в вашем модуле и не экспортирован, никто не может создать экземпляр с этим типом, поэтому любой экземпляр, который унифицируется сX
, должен быть задан с переменной типа. - person user2407038   schedule 09.01.2015