Question

It seems as though this isn't possible, but here's an example of what I have working:

{-# LANGUAGE PolyKinds , MultiParamTypeClasses , FlexibleInstances , OverlappingInstances #-}

data Proxy a = Proxy

class Test pt t where
    test :: pt -> t -> IO ()

instance Test (Proxy t) t where
    test _ _ = putStrLn "MATCHES"

-- I would like to combine these:
instance Test (Proxy t) (t a) where
    test _ _ = putStrLn "MATCHES2"
instance Test (Proxy t) (t a b) where
    test _ _ = putStrLn "MATCHES3"
--etc.

instance Test (Proxy t) x where
    test _ _ = putStrLn "FAIL"

With PolyKinds and our instances above our t in Proxy t can be arity * -> *, or * -> * -> * and the code works correctly, however supporting ts of higher arity requires adding an arbitrary number of additional instances. Is there a way to combine those two instances into a single instance that means "t fully-applied to any k arguments"?

Was it helpful?

Solution

I just realized: I can have a recursive instance that keeps "chopping off" arguments until its found to be equal, although this requires contortions and I'm not yet sure how great an idea this is:

{-# LANGUAGE PolyKinds , MultiParamTypeClasses , FlexibleInstances , OverlappingInstances 
 , FlexibleContexts  -- these are new
 , ScopedTypeVariables
 #-}

data Proxy a = Proxy

class Test pt t where
    test :: pt -> t -> IO ()

-- ...also, as you can see I've had to make the second argument a `Proxy` since I can't
-- do the type-chopping thing to real values. I don't think that should be too much of
-- an issue for my use case though.
instance Test (Proxy t) (Proxy t) where
    test _ _ = putStrLn "MATCHES"
-- we need this extra instance for an explicit match that is more specific than the instance below:
instance Test (Proxy (t a)) (Proxy (t a)) where
    test _ _ = putStrLn "MATCHES"

instance (Test (Proxy t) (Proxy ta))=> Test (Proxy t) (Proxy (ta b)) where
    test p _ = test p (Proxy :: Proxy ta)

instance Test (Proxy t) x where
    test _ _ = putStrLn "FAIL"

Any other solutions welcome.

EDIT: I just made a little utility library called proxy-kindness that lets you do some fancy and useful kind-polymorhpic manipulations of proxy values.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top