4

似乎这是不可能的,但这是我工作的一个例子:

{-# 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"

我们inPolyKinds上面的 and 我们的实例可以是 arity ,或者and 代码可以正常工作,但是支持更高arity 的 s 需要添加任意数量的额外实例。有没有办法将这两个实例组合成一个实例,这意味着“完全应用于任何参数”?tProxy t* -> ** -> * -> *ttk

4

1 回答 1

1

我刚刚意识到:我可以有一个递归实例,它一直“切断”参数,直到发现它相等,尽管这需要扭曲,我还不确定这是一个多么好的想法:

{-# 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"

欢迎任何其他解决方案。

编辑:我刚刚制作了一个名为的小实用程序库proxy-kindness,它可以让您对代理值进行一些花哨且有用的多态操作。

于 2013-11-12T21:04:18.237 回答