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"

withとinPolyKindsの上のインスタンスはアリティにすることができます。または、コードは正しく動作しますが、より高いアリティの をサポートするには、任意の数の追加インスタンスを追加する必要があります。これらの 2 つのインスタンスを「任意の引数に完全に適用される」ことを意味する単一のインスタンスに結合する方法はありますか?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"

他のソリューションは歓迎します。

EDIT :プロキシ値の派手で便利な種類の多態的な操作を行うことができる、と呼ばれる小さなユーティリティライブラリを作成しました。proxy-kindness

于 2013-11-12T21:04:18.237 に答える