私はData.Typeable.gcast
、ある種の型族で機能するバリアントを書き込もうとしてい* -> *
ます。私が探しているのは:
{-# LANGUAGE TypeFamilies #-}
import Data.Typeable
type family T
gcastT :: (Typeable a,Typeable b) => T a -> Maybe (T b)
gcastT = undefined -- but that's not working too well!
に類推して行きgcast :: (Typeable a,Typeable b) => f a -> Maybe (f b)
ます。
これは可能ですか?
コンテキストをに変更することもでき(Typeable (T a),Typeable (T b)) =>
ますが、美的理由からこの署名を使用したいと思います。結局のところ、gcast
必要ありません。Typeable1 f
私が実際に達成したいことについて間違った問題を解決している場合の背景:私の目標は関数を書くことですmatchAndExtract
:
matchAndExtract :: (Eq a, Typeable a, Eq b, Typeable b) => a -> b -> T b -> Maybe (T a)
matchAndExtract x k v = if (cast x == Just k) then gcastT v else Nothing
これは、同じタイプであり、等しいかどうかをチェックx
し、提供されたものを返します(これは、それまでに-Tと同じであることがわかっていますが、単射ではないかもしれませんが、関数です!)または、それ以外の場合。k
T b
T a
Nothing
T a
問題のあるものをでラップしnewtype
、を使用してgcast
、再度ラップを解除することで回避策があります。
matchAndExtractF :: (Eq a, Typeable a, Eq b, Typeable b) => a -> b -> f b -> Maybe (f a)
matchAndExtractF x k v = if (cast x == Just k) then gcast v else Nothing
newtype WrapT a = WrapT { unWrapT :: T a }
matchAndExtractViaWrap :: (Eq a, Typeable a, Eq b, Typeable b) => a -> b -> T b -> Maybe (T a)
matchAndExtractViaWrap x k v = fmap unWrapT $ matchAndExtractF a k (WrapT v)
しかし、それは私を間違った方法でこすります!これは、 ;T a
のインスタンスではないインスタンスでも機能します。これもまた、コンテキストが必要ではないことTypeable
を示しているように思えます。Typeable (T a)
WrapT
回避策は完全に受け入れられますが、スプリアスタイプを取り除きたいと思います。