我正在玩一个使用存在量化的 ConduitT 风格的 monad,我正在玩 whack-a-mole 试图让类型统一。这个场景有两个版本:
在这里,Await i
有一个存在量化的a
,它允许await
方法传递它i -> Await i -> a
想要的任何类型。
{-# LANGUAGE RankNTypes #-}
newtype Piped r a = Piped { unPiped :: forall b. r -> (r -> a -> b) -> b }
instance Functor (Piped r) where
fmap f (Piped c) = Piped $ \r rest -> c r (\r -> rest r . f)
runPiped :: Piped r a -> r -> a
runPiped (Piped p) r = p r $ \_ -> id
newtype Await i = Await { unAwait :: forall a. Yield i a -> a }
newtype Yield i a = Yield { unYield :: i -> Await i -> a }
runAwait :: Await i -> (i -> Await i -> a) -> a
runAwait (Await await) = await . Yield
runYield :: Yield i a -> i -> (Yield i a -> a) -> a
runYield (Yield yield) i = yield i . Await
-- broke ^^^^^
-- because Await swallows the type of `a`
await :: forall i a y. Piped (Await i, y) i
await = Piped $
\(a, y) f -> runAwait a $ \i a' -> f (a', y) i
失败:
• Couldn't match type ‘Yield i a -> a’
with ‘forall a1. Yield i a1 -> a1’
Expected type: (Yield i a -> a) -> Await i
Actual type: (forall a. Yield i a -> a) -> Await i
• In the second argument of ‘(.)’, namely ‘Await’
该runYield
方法已损坏,因为它无法在Await i
with中统一存在限定的类型参数a
。
第二种情况:
为了修复runYield
,Await
现在指定a
,与Await i a
统一Yield i a
。但是,既然a
指定了,yield
就不能将它传递给它喜欢的Yield i b
任何值b
:
newtype Piped r a = Piped { unPiped :: forall b. r -> (r -> a -> b) -> b }
newtype Await i a = Await { unAwait :: Yield i a -> a }
newtype Yield i a = Yield { unYield :: i -> Await i a -> a }
runAwait :: Await i a -> (i -> Await i a -> a) -> a
runAwait (Await await) = await . Yield
runYield :: Yield i a -> i -> (Yield i a -> a) -> a
runYield (Yield yield) i = yield i . Await
await :: Piped (Await i a, y) i
await = Piped $
\(a, y) f -> runAwait a $ \i a' -> f (a', y) i
-- ^^^^^^
失败:
• Couldn't match type ‘b’ with ‘a’
‘b’ is a rigid type variable bound by
a type expected by the context:
forall b. (Await i a, y) -> ((Await i a, y) -> i -> b) -> b
Expected type: (Await i a, y)
Actual type: (Await i b, y)
所以我似乎需要两种方式,有时是存在量化的,有时是具体的。我已经尝试创建包装器来隐藏额外的类型参数,切换newtype
为 有任何想法吗?data
Await i a -> Await i b