我正在尝试编写Data.Typeable.gcast
的变体,它适用于种类为* -> *
的类型族。我正在寻找的是:如何为类型族编写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
和k
然后返回提供的T b
(我们当时知道它与T a
相同 - T可能不是内射的,但它是是的函数!)或Nothing
,否则返回提供的T b
。
我已经通过包装违规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
类型。
不可能。类型族不是内射的,因此你不能解决它们以这种方式来的约束。 – 2013-02-28 21:44:04
但知道'可键入'并不意味着'可键入(T a)'! – 2013-03-01 00:12:30
@DanielWagner:没错,但是我有限的测试包括一个'T a'显然不是'Typeable'成员的情况。现在我不明白为什么'matchAndExtractViaWrap'工作!这可能是GHC中的错误(我正在使用7.6.1)?我会尝试明天实施'unsafeCoerce' ... – yatima2975 2013-03-01 00:40:53