我可以这样定义一个多类自然变换:
type family (~>) :: k -> k -> *
type instance (~>) = (->)
newtype NT a b = NT { apply :: forall x. a x ~> b x }
type instance (~>) = NT
它适用于所有类型,所以我可以定义例如。
left :: Either ~> (,)
left = NT (NT (Left . fst))
这很酷也很鼓舞人心。但不管我耍了多少把戏,我似乎都不能在游戏中得到一些可变的东西
返回
类型。我想
type family (:*:) :: k -> k -> k
type instance (:*:) = (,)
type instance (:*:) = ???
似乎这是不可能的,因为类型族需要完全饱和,并且只能在中引入类型构造函数
*
.
我甚至试过一些相当下流的把戏
type instance (:*:) = Promote2 (:*:)
type family Promote2 :: (j -> k -> l) -> (a -> j) -> (a -> k) -> (a -> l) where
promote2_law :: Promote2 f x y z :~: f (x z) (y z)
promote2_law = unsafeCoerce Refl
fstP :: forall (a :: k -> *) (b :: k -> *) (c :: k). (a :*: b) c -> a c
fstP = case promote2_law @(:~:) @a @b @c of Refl -> NT (\(a,b) -> a)
我不知道这是否有任何工作的希望,因为我还没有想过如何更高类的东西是“代表”。但GHC知道我在撒谎
⢠Couldn't match type â(,)â with âPromote2 (,) aâ
Inaccessible code in
a pattern with constructor: Refl :: forall k (a :: k). a :~: a,
还有其他的窍门吗?