This code fails to compile with this error
src/JsonParser.hs:33:37-62: error:
* Couldn't match type `b1' with `b'
`b1' is a rigid type variable bound by
the type signature for:
resultantRunParse :: forall b1. String -> Maybe (String, b1)
at src/JsonParser.hs:29:5-52
`b' is a rigid type variable bound by
the type signature for:
fmap :: forall a b. (a -> b) -> Parser a -> Parser b
at src/JsonParser.hs:27:11-42
Expected type: Maybe (String, b1)
Actual type: Maybe (String, b)
The code:
import Prelude
newtype Parser a = Parser
{ runParser :: String -> Maybe (String, a)
}
instance Functor Parser where
fmap :: (a -> b) -> Parser a -> Parser b
fmap f (Parser p) = Parser resultantRunParse where
-- THIS FUNCTION TYPE DECLARATION IS THE PROBLEM
-- IF I REMOVE THE TYPE DECLARATION, IT WORKS
resultantRunParse :: String -> Maybe (String, b)
resultantRunParse input =
case p input of
Nothing -> Nothing
Just (remaining, parsed) -> Just (remaining, f parsed)
I tried the signature resultantRunParse :: forall b1. String -> Maybe (String, b1) suggested in the error message and that also didnt work.
Also, making the resultantRunParse = undefined and keeping the type signature also worked. Very strange!
What is the correct signature for this function?
The type signature must contain b, but it must be the same one as the b used in the enclosing function. This is impossible without scoped type variables:
https://wiki.haskell.org/Scoped_type_variables
To us this, add a comment to the top of your file:
{-# LANGUAGE ScopedTypeVariables #-}
Then, use an explicit forall b. in the enclosing function’s type signature.
Without scoped type variables, there is no way to write b in the type signature and make it the same b as the one used in the enclosing function.
(My personal recommendation is to just not use a type signature here. It is not necessary.)
First get comfortable writing the instance by hand, then you can derive it. This type looks a lot like StateT, the state monad transformer where the order of the tuple is swapped.
type StateT :: Type -> MonadTransformer
newtype StateT s m a = StateT (s -> m (a, s))
Your Functor Parser instance can be derived via it if you are willing to swap the order
{-# Language DerivingVia #-}
{-# Language StandaloneKindSignatures #-}
import Control.Monad.State
import Data.Kind
type Parser :: Type -> Type
newtype Parser a = Parser
{ runParser :: String -> Maybe (a, String)
}
deriving Functor
via StateT String Maybe
You can derive more instances in this manner.
import Control.Applicative
import Control.Monad.Catch
import Control.Monad.Except
import Control.Monad.State
import Data.Kind
import Data.Monoid
newtype Parser a = Parser ..
deriving
( Functor, Applicative, Alternative
, Monad, MonadPlus, MonadFix, MonadThrow
, MonadFail, MonadError (), MonadState String )
via StateT String Maybe
-- pointwise lifting
-- (<>) = liftA2 (<>)
-- mempty = pure mempty
-- deriving (Semigroup, Monoid, Num, Bounded)
-- via Ap Parser a
-- or Alternative
-- (<>) = (<|>)
-- mempty = empty
deriving (Semigroup, Monoid)
via Ap Parser a
See the output of :instances command
:instances StateT String Maybe
:instances Ap Parser _
:instances Alt Parser _
The last two require partial type signatures :set -XPartialTypeSignatures -Wno-partial-type-signatures.
Related
For a uni assignment, we have been given a line of Haskell code which shows:
newtype TC a = TC ([Id] -> Either TypeError ([Id], a))
Firstly, TypeError is something which needs to be implemented by us for the assignment so I can't post the data declaration here, but my question is this. How do I read the code above? What is the a right after the newtype TC? I also don't understand how TC is being reused to the right of the equals sign.
I think a here is a type variable since newtype works similarly to data. I don't know how knowing this will help my understanding.
What is the a right after the newtype TC?
The a in the newtype declaration
newtype TC a = ...
expresses much the same as the x in a function declaration
f x = ...
a is a type parameter. So you'll be able to use TC as, for example, TC Int or TC Bool, similar to how you're able to use f like f 1 or f "bla bla" (depending on its type).
The case TC Int is equivalent to the following alternative:
newtype TCInt = TCInt ([Id] -> Either TypeError ([Id], Int))
I also don't understand how TC is being reused to the right of the equals sign.
That is a bit of a confusing quirk in Haskell. Actually TC is not reused, rather you're declaring two separate entities which are both called TC. You could also call them differently:
newtype TC_T a = TC_V ([Id] -> Either TypeError ([Id], a))
TC_T is a type constructor. This is the thing that will appear in type signatures, i.e. TC_T Int or TC_T Bool.
TC_V is a value constructor. You use this when, well, generating values of type TC_T Int or TC_T Bool.
So for example, you might write these:
tci :: TC_T Int
tci = TC_V (\ids -> Right (ids, 37))
tcb :: TC_T Bool
tcb = TC_V (\ids -> Right (reverse ids, False))
With your original version it looks like this:
tci :: TC Int
tci = TC (\ids -> Right (ids, 37))
tcb :: TC Bool
tcb = TC (\ids -> Right (reverse ids, False))
...but it's still two separate things both called TV here. Most newtypes in Haskell call the type- and value constructors the same, but often only the type constructor is exported from a module and the value constructor left as an implementation detail.
Most of this is the same for data as for newtype. You could as well have
data TC a = TC ([Id] -> Either TypeError ([Id], a))
... the only difference to the newtype version is a subtle indirection: if it's data, then the compiler inserts an indirection which allows a bit more lazyness, but in this case there's hardly a point to doing that.
In practice, you generally use data only when you need multiple constructors and/or a constructor with multiple fields, which newtype does not support.
The benefit of newtype over data is that you can derive via the type that underlies it:
{-# Language DerivingVia #-}
{-# Language StandaloneKindSignatures #-}
import Control.Applicative (Alternative)
import Control.Monad (MonadPlus)
import Control.Monad.Except (ExceptT(..), Except)
import Control.Monad.Fix (MonadFix)
import Control.Monad.State (StateT(..), MonadState)
import Data.Functor.Identity (Identity(..))
import Data.Kind (Type)
type TC :: Type -> Type
newtype TC a = MkTC ([Id] -> Either TypeError (a, [Id]))
deriving
( Functor, Applicative, Alterantive
, Monad, MonadPlus, MonadState [Id], MonadFix
)
via StateT [Id] (Except TypeError)
-- Alternative and MonadPlus rely on these
instance Semigroup TypeError ..
instance Monoid TypeError ..
I had to swap the tuple but this works because of three newtypes: TC a, StateT s m a and ExceptT. The compiler generates an instance for each newtype witnessing that it has the same runtime representation as the underlying type.
This is called representational equality and is witnessed by Coercible.
-- instance Coercible (StateT s m a) (s -> m (a, s))
type StateT :: Type -> (Type -> Type) -> (Type -> Type)
newtype StateT s m a = MkStateT (s -> m (a, s))
-- instance Coercible (ExceptT e m a) (m (Either e a))
type ExceptT :: Type -> (Type -> Type) -> (Type -> Type)
newtype ExceptT e m a = MkExceptT (m (Either e a))
This entails that TC a is coercible to StateT [Id] (Except TypeError) a and thus we can use coerce-based deriving strategies to carry instances between them (like GeneralizedNewtypeDeriving or DerivingVia).
TC a
={Coercible}
[Id] -> Either TypeError (a, [Id])
={Coercible}
[Id] -> ExceptT TypeError Identity (a, [Id])
={Except e = ExceptT e Identity}
[Id] -> Except TypeError (a, [Id])
={Coercible}
StateT [Id] (Except TypeError) a
GeneralizedNewtypeDeriving only works on newtypes but this does not mean that DerivingVia only works on newtypes. You can dervive many instances for data, for example by Applicative lifting methods over TC (Ap TC a).
Making it a newtype does simplify things, the Applicative can be derived through the state transformer so we don't need to write any instance by hand.
data TC a = MkTC ..
..
deriving (Semigroup, Monoid, Num, Bounded)
via Ap TC a
The TC name serves two purposes in your code ('punning'). I separate them into two different names, for TC and the transformers.
The left-hand side is the type constructor:
>> :k TC
TC :: Type -> Type
>> :k StateT
StateT :: Type -> (Type -> Type) -> (Type -> Type)
>> :k ExceptT
ExceptT :: Type -> (Type -> Type) -> (Type -> Type)
and the right-hand side is the value constructor, which I added a Mk for disambiguation:
>> :t MkTC
MkTC :: ([Id] -> Either TypeError (a, [Id])) -> TC a
>> :t MkStateT
MkStateT :: (s -> m (a, s)) -> StateT s m a
>> :t MkExceptT
MkExceptT :: m (Either e a) -> ExceptT e m a
The a :: Type is an argument to the type constructor:
TC :: Type -> Type
TC a :: Type
Without a type argument none of those instaces would kind-check because all of those instances require an "unary type constructor" (Type -> Type) as an argument. That is to say, a type parameterised by a type:
Functor :: (Type -> Type) -> Constraint
Applicative :: (Type -> Type) -> Constraint
Alternative :: (Type -> Type) -> Constraint
Monad :: (Type -> Type) -> Constraint
MonadPlus :: (Type -> Type) -> Constraint
MonadState [Id] :: (Type -> Type) -> Constraint
MonadFix :: (Type -> Type) -> Constraint
Not sure if I'm phrasing the question correctly in the title but I'm trying to do something like this:
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
module Lib where
import Control.Lens
data Foo = Foo {_bar1 :: Int
,_bar2 :: String
,_bar3 :: [Rational]} deriving (Show, Eq)
makeFieldsNoPrefix ''Foo
aFoo :: Foo
aFoo = Foo 33 "Hm?" [1/6,1/7,1/8]
stringToLens :: (HasBar1 s a, Functor f, HasBar2 s a, HasBar3 s a) => String -> Maybe ((a -> f a) -> s -> f s)
stringToLens str = case str of
"bar1" -> Just bar1
"bar2" -> Just bar2
"bar3" -> Just bar3
_ -> Nothing
updateFoo :: (HasBar1 a1 a2, HasBar2 a1 a2, HasBar3 a1 a2, Read a2) => String -> String -> a1 -> Maybe a1
updateFoo lensStr valStr myFoo = case stringToLens lensStr of
Just aLens -> Just $ set aLens (read valStr) myFoo
Nothing -> Nothing
newFoo :: Maybe Foo
newFoo = updateFoo "bar1" 22 aFoo
{--
Couldn't match type ‘[Char]’ with ‘Int’
arising from a functional dependency between:
constraint ‘HasBar2 Foo Int’ arising from a use of ‘updateFoo’
instance ‘HasBar2 Foo String’
at /home/gnumonic/Haskell/Test/test/src/Lib.hs:14:1-24
• In the expression: updateFoo "bar1" 22 aFoo
In an equation for ‘newFoo’: newFoo = updateFoo "bar1" 22 aFoo
--}
(Ignore the use of read here, I do it the "right way" in the actual module I'm working on.)
That, obviously, doesn't work. I thought that making a typeclass along the lines of this might work:
class OfFoo s a where
ofFoo :: s -> a
instance OfFoo Foo Int where
ofFoo foo = foo ^. bar1
instance OfFoo Foo String where
ofFoo foo = foo ^. bar2
instance OfFoo Foo [Rational] where
ofFoo foo = foo ^. bar3
But there doesn't seem to be a way of adding that class to the constraint in such a way that the stringToLens function is actually usable, even though it typechecks fine until I try to use it. (Although it doesn't even typecheck if I use makeLenses instead of makeFields, and I'm not really sure why.)
E.g. (with the maybe removed for simplicity):
stringToLens :: (HasBar1 s a, Functor f, HasBar2 s a, HasBar3 s a, OfFoo s a) => String -> (a -> f a) -> s -> f s
stringToLens str = case str of
"bar1" -> bar1
"bar2" -> bar2
"bar3" -> bar3
That typechecks but is pretty much useless, since any attempt to apply the function throws the functional dependency error.
I also tried using the Reified newtypes from Control.Lens.Reify, but that didn't fix the functional dependency issue.
What I can't figure out is that if I modify the updateFoo like so:
updateFoo2 :: Read a => ASetter Foo Foo a a -> String -> Foo -> Foo
updateFoo2 aLens val myFoo = set aLens (read val) myFoo
Then this works:
testFunc :: Foo
testFunc = updateFoo2 bar1 "22" aFoo
But this throws the functional dependency error at myLens1 whenever it's used (although the definition typechecks):
testFunc' :: Foo
testFunc' = updateFoo2 (stringToLens "bar1") 22 aFoo -- Error on (stringToLens "bar1")
myLens1 :: (HasBar1 s a, Functor f, HasBar2 s a, HasBar3 s a, OfFoo s a) => (a -> f a) -> s -> f s
myLens1 = stringToLens "bar1" -- typechecks
testFunc2 :: Foo
testFunc2 = updateFoo2 myLens1 "22" aFoo -- Error on myLens1
So I can define a stringToLens function, but it's pretty much useless...
Unfortunately I wrote a bunch of code on the assumption that something like this could be made to work. I'm writing a packet generator, and if I can get this to work then I have a pretty convenient way of quickly adding support for new protocols. (The rest of my code extensively uses lenses for a variety of purposes.) I can think of a few workarounds but they're all extremely verbose and require either a lot of template Haskell (to generate a copy of every function for each new protocol data type) or a lot of boilerplate (i.e. creating dummy types to signal the correct type for read in the updateFoo functions).
Is there any way to do what I'm trying to do here with lenses, or is it just impossible without something like impredicative types? If not, is there a better workaround the the one's I'm seeing?
At this point my best guess is that there's just not enough information for the compiler to infer the type of the value string without having a fully evaluated lens.
But it seems like something along these lines should be possible, since by the time the output of stringToLens is passed to updateFoo, it will have a definite (and correct) type. So I'm stumped.
Implementing stringToLens would require something like dependent types, because the type of the resulting Lens depends on an argument's value: the field name. Haskell doesn't have full dependent types, although they can be emulated with more or less difficulty.
In updateFoo, you take as parameter both the field name (lensStr) and the "serialized" form of the field's value (valStr), and return an update function for some datatype. Can we have that without getting dependent-ish?
Imagine that, for a certain type Foo, you had something like a Map FieldName (String -> Maybe (Foo -> Foo)). For each field name, you would have a function that parsed the field's value and, if successful, returned an update function for Foo. No dependent types would be required, as the parsing of each field's value would be hidden behind functions with a uniform signature.
How to build such map-of-parsers-returning-updaters for a given type? You could build it manually, or it could be derived with the help of some generics wizardry.
Here's a possible implementation based on the red-black-record library (although it would be better to base it on the more established generics-sop). Some preliminary imports:
{-# LANGUAGE DeriveGeneric, FlexibleContexts, FlexibleInstances, #-}
{-# LANGUAGE TypeApplications, TypeFamilies, TypeOperators, ScopedTypeVariables #-}
import qualified Data.Map.Strict as Map
import Data.Map.Strict
import Data.Monoid (Endo (..))
import Data.Proxy
import Data.RBR
( (:.:) (Comp),
And,
Case (..),
FromRecord (fromRecord),
I (..),
IsRecordType,
K (..),
KeyValueConstraints,
KeysValuesAll,
Maplike,
Record,
ToRecord (toRecord),
collapse'_Record,
cpure'_Record,
injections_Record,
liftA2_Record,
unI,
)
import GHC.Generics (Generic)
import GHC.TypeLits
The implementation itself:
type FieldName = String
type TextInput = String
makeUpdaters ::
forall r c.
( IsRecordType r c, -- Is r convertible to the rep used by red-black-record?
Maplike c, -- Required for certain applicative-like operations over the rep.
KeysValuesAll (KeyValueConstraints KnownSymbol Read) c -- Are all fields readable?
) =>
Proxy r ->
Map FieldName (TextInput -> Maybe (r -> r))
makeUpdaters _ =
let parserForField :: forall v. Read v
=> FieldName -> ((,) FieldName :.: (->) TextInput :.: Maybe) v
parserForField fieldName = Comp (fieldName, Comp read)
parserRecord = cpure'_Record (Proxy #Read) parserForField
injectParseResult ::
forall c a.
Case I (Endo (Record I c)) a -> -- injection into the record
((,) FieldName :.: (->) TextInput :.: Maybe) a -> -- parsing function
(FieldName, Case I (Maybe (Endo (Record I c))) TextInput)
injectParseResult (Case makeUpdater) (Comp (fieldName, Comp readFunc)) =
( fieldName,
( Case $ \textInput ->
let parsedFieldValue = readFunc . unI $ textInput
in case parsedFieldValue of
Just x -> Just $ makeUpdater . pure $ x
Nothing -> Nothing ) )
collapsed :: [(FieldName, Case I (Maybe (Endo (Record I c))) TextInput)]
collapsed = collapse'_Record $
liftA2_Record
(\injection parser -> K [injectParseResult injection parser])
injections_Record
parserRecord
toFunction :: Case I (Maybe (Endo (Record I c))) TextInput
-> TextInput -> Maybe (r -> r)
toFunction (Case f) textInput = case f $ I textInput of
Just (Endo endo) -> Just $ fromRecord . endo . toRecord
Nothing -> Nothing
in toFunction <$> Map.fromList collapsed
A type in which to test it:
data Person = Person {name :: String, age :: Int} deriving (Generic, Show)
-- let updaters = makeUpdaters (Proxy #Person)
--
instance ToRecord Person
instance FromRecord Person
What is the most direct way to bind a type variable when pattern matching in a Gadt ?
#!/usr/bin/env stack
-- stack script --resolver lts-13.1
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE GADTs, ScopedTypeVariables #-}
{-# LANGUAGE DataKinds #-}
module Main where
import Data.Proxy
import GHC.TypeLits
main :: IO ()
main = undefined
data Kind where
Index :: Symbol -> Kind
data Gadt (f::Kind) where
Lit :: KnownSymbol s => Gadt ('Index s)
Binding s directly would fail
format :: Gadt f -> String
format (Lit :: Gadt ('Index s)) = undefined -- KO
with error
• Couldn't match type ‘f’ with ‘'Index s’
‘f’ is a rigid type variable bound by
the type signature for:
format :: forall (f :: Kind). Gadt f -> String
Expected type: Gadt f
Actual type: Gadt ('Index s)
A type function can extract the type, but aren't there more direct way to do this ?
format (Lit :: Gadt i) = symbolVal (Proxy :: TLabel i)
type family TLabel (a::Kind)
type instance TLabel ('Index s ) = Proxy s
The only way I see is to add a Proxy to bind the type variable with ScopedTypeVariables.
data Gadt a where
Lit :: KnownNat s => Proxy s -> Gadt ('Index s)
format :: Gadt a -> String
format (Lit (Proxy :: Proxy s)) = undefined
If you are worried about the extra allocation, the field can be unpacked. (EDIT: removed previous mention of Proxy# because that doesn't seem necessary).
import Data.Proxy
-- This should be as efficient as the original Gadt with a nullary Lit
data Gadt a where
Lit :: {-# UNPACK #-} !(Proxy r) -> Gadt ('Index r)
format :: Gadt a -> String
format (Lit (_ :: Proxy r)) = undefined
On the longer term, the following GHC proposal will address this issue: Type Applications in Patterns.
-- The original type
data Gadt a where
Lit :: forall s. Gadt ('Index s)
format :: Gadt a -> String
format (Lit #s) = ...
The following file Poly.hs file
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE RankNTypes #-}
module Poly () where
type ListModifier s = forall a. s -> [a] -> [a]
instance Monoid (ListModifier s) where
mempty = const id
mappend f g st = f st . g st
Gets the typechecker to complain:
Poly.hs:8:10: Illegal polymorphic or qualified type: ListModifier s …
In the instance declaration for ‘Monoid (ListModifier s)’
Compilation failed.
Initially I though it couldn't compose the rank 2 types but:
λ> :t (undefined :: forall a . a -> String ) . (undefined :: forall b . String -> b)
(undefined :: forall a . a -> String ) . (undefined :: forall b . String -> b)
:: String -> String
I feel the Poly module is in some way inherently inconsistent but I can't put my finger on the problem.
ListModifier is a type alias, not a “real” type. Type aliases are essentially macros at the type level, always expanded by the typechecker before actually typechecking. That means your instance declaration is equivalent to the following:
instance Monoid (forall a. s -> [a] -> [a]) where
Even if that were allowed, it would overlap with the existing Monoid (a -> b) instance, so it still wouldn’t work. The larger problem, however, is that you can’t have an instance defined on a forall-quantified type because it wouldn’t make sense from the perspective of instance resolution.
What you could do instead is define a fresh type instead of a type alias using newtype:
newtype ListModifier s = ListModifier (forall a. s -> [a] -> [a])
Now you can define a Monoid instance, since typeclass resolution only needs to look for the ListModifier type, which is much simpler to match on:
instance Monoid (ListModifier s) where
mempty = ListModifier (const id)
mappend (ListModifier f) (ListModifier g) = ListModifier (\st -> f st . g st)
Alternatively, you could keep your type alias and define a newtype with a different name, like ReifiedListModifier, then define an instance on that, and you could only do the wrapping when you need to store a ListModifier in a container or use a typeclass instance.
Using the singletons library, this simple function compiles and works. But, ghci and ghc disagree about the type signature of it, and if either of their suggestions is pasted into the code, it will fail to compile.
What type signature will GHC accept? ghc-7.10.3, singletons-2.0.1
{-# LANGUAGE DataKinds, PolyKinds, TypeOperators, TypeFamilies, GADTs, UndecidableInstances, FlexibleContexts #-}
import Data.Proxy (KProxy(..))
import Data.Singletons
import Data.Singletons.Prelude
-- ghc rejects this type signature, but if I leave it off, ghci :t shows exactly this.
matches :: (Eq (DemoteRep 'KProxy), SingKind 'KProxy) => DemoteRep 'KProxy -> Sing a -> Bool
matches m s = m == fromSing s
t :: Sing True
t = sing
demo :: Bool
demo = matches True t
GHC's error with above type signature:
Couldn't match type ‘DemoteRep 'KProxy’ with ‘DemoteRep 'KProxy’
NB: ‘DemoteRep’ is a type function, and may not be injective
The kind variable ‘k2’ is ambiguous
Use -fprint-explicit-kinds to see the kind arguments
Expected type: DemoteRep 'KProxy -> Sing a -> Bool
Actual type: DemoteRep 'KProxy -> Sing a -> Bool
In the ambiguity check for the type signature for ‘matches’:
matches :: forall (k :: BOX)
(k1 :: BOX)
(k2 :: BOX)
(k3 :: BOX)
(a :: k3).
(Eq (DemoteRep 'KProxy), SingKind 'KProxy) =>
DemoteRep 'KProxy -> Sing a -> Bool
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
In the type signature for ‘matches’:
matches :: (Eq (DemoteRep KProxy), SingKind KProxy) =>
DemoteRep KProxy -> Sing a -> Bool
ghc -Wall suggests a different type signature, but the BOX stuff won't be accepted either:
Top-level binding with no type signature:
matches :: forall (k :: BOX) (a :: k).
(Eq (DemoteRep 'KProxy), SingKind 'KProxy) =>
DemoteRep 'KProxy -> Sing a -> Bool
'KProxy at the type level is like Proxy at the value level: it has a phantom. Just as we write Proxy :: Proxy a with the phantom type a at the value level, we have to turn on kind signatures and write 'KProxy :: KProxy k with a phantom kind k at the type level. Hopefully that analogy makes a kind of sense. Here's what it looks like:
{-# LANGUAGE DataKinds, PolyKinds, TypeOperators, TypeFamilies, GADTs, UndecidableInstances, FlexibleContexts, KindSignatures #-}
import Data.Proxy (KProxy(..))
import Data.Singletons
import Data.Singletons.Prelude
matches ::
( Eq (DemoteRep ('KProxy :: KProxy k))
, SingKind ('KProxy :: KProxy k)
) => DemoteRep ('KProxy :: KProxy k) -> Sing (a :: k) -> Bool
matches m s = m == fromSing s
This type variable k will occur in both DemoteRep ... and Sing ..., which is what lets us type-check m == fromSing s.
GHCi, though sweet and usually smart, has no idea that the type signature needs "another level of indirection" and needs an introduced kind variable.
Aside
I would caution aginst the majority opinion here that -fprint-explicit-kinds is helpful:
λ> :t matches
matches
:: (Eq (DemoteRep * ('KProxy *)), SingKind * ('KProxy *)) =>
DemoteRep * ('KProxy *) -> Sing * a -> Bool
That, to me, doesn't really point a finger at what's happening here. I was only able to piece together everything by looking up the signatures for DemoteRep, 'KProxy, and Sing with the handy-dandy :info command.
The trouble is that you're using (essentially) a kind class, but you're not pinning down kinds properly. In particular, the three occurrences of 'KProxy could all refer to different kinds. A common approach would be to name the proxy using an equality constraint, and use that name repeatedly. This saves a bit of typing compared to giving every proxy a signature:
matches :: (kproxy ~ ('KProxy :: KProxy k),
Eq (DemoteRep kproxy),
SingKind kproxy)
=> DemoteRep kproxy
-> Sing (a :: k) -> Bool
This makes it clear that the proxies should all be the same, and in particular should have the same kind as the type passed to Sing.