我正在尝试编写一个Data.Typeable.gcast
适用于 kind 类型系列的变体* -> *
。我正在寻找的是:
{-# 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
andk
是否属于同一类型并且相等,然后返回提供的T b
(我们那时知道它与T a
- T 可能不是单射的,但它是一个函数!)或Nothing
,否则。
我有一个解决方法,将违规内容包装T a
在 a newtype
、 using 中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
类型。