Сначала несколько замечаний:
- Не указывайте такой экземпляр . Этот экземпляр будет соответствовать любому формату
f, независимо от тогоf, действительно ли он вWrapperклассе. В частности, это также противоречило бы со стандартными экземплярами, такими какFromJSON (Vector a), даже еслиVectorэто не может быть (хороший) экземплярWrapper. Причиной этого является то, что система классов Haskell основана на предположении открытого мира : компилятор никогда не может предположить, что тип не находится в каком-то классе, потому что любой мог, по крайней мере технически говоря, добавить экземпляр позже. -
Я бы советовал не использовать
Proxyв новом коде. Я всегда считалProxyуродливый хак, едва менее уродливым, чемundefined :: Tаргументы, которые обычно использовались для этого в старом кодеке Haskell. В новом GHC, то проблема была решена должным образом-XAllowAmbiguousTypesс-XTypeApplications; они позволяют просто сделать подпись{-# LANGUAGE AllowAmbiguousTypes #-} class Wrapper f where ... name :: Stringа затем вместо
name (Proxy :: Proxy (f a))записиname @f.
Теперь к реальной проблеме: ваш код не работает, потому что переменные типа в стандартном Haskell всегда принадлежат только контексту подписи / класса одного типа, но не могут использоваться в коде, который его определяет. IOW, переменные типа не используют те же области имен , что и переменные значения, поэтому, когда вы упоминаете Proxy (f a)компилятор a € ?disambiguatesa €? переменные типа to f0и a0. Это немного глупый недостаток Haskell98, и он адресован -XScopedTypeVariablesрасширением (вместе с ключевым словом ?aka forall). Следующее будет компилироваться само по себе:
{-# LANGUAGE ScopedTypeVariables, UnicodeSyntax #-}
instance ? f a . (IsString a, FromJSON a, Wrapper f) => FromJSON (f a) where
parseJSON (String s) = wrap <$> pure (fromString $ unpack s)
parseJSON invalid = typeMismatch (name (Proxy :: Proxy (f a))) invalid
Как я уже сказал, такой пример не должен определяться. Я думаю, что вы действительно хотите что-то вроде
{-# LANGUAGE DataKinds, KindSignatures, TypeApplications #-}
import GHC.TypeLits (Symbol, KnownSymbol, symbolVal)
data Wrapper (n :: String) (a :: *)
= Wrapper a
| TypeMismatch String
instance ? a s . (IsString a, FromJSON a, KnownSymbol s)
=> FromJSON (Wrapper s a) where
parseJSON (String s) = Wrapper <$> pure (fromString $ unpack s)
parseJSON invalid = TypeMismatch $ symbolVal @s Proxy
Никаких занятий не требуется.