我想基于ContT
创建一个通用的IO形式。我创建了一个GADT来表示不同的IO操作:
data Cmd a where
PutChar :: Char -> Cmd ()
GetChar :: Cmd Char
我编写了一个函数,将这些函数转换为IO
命令,以便在IO monad中使用,如下所示:
continueIO :: Cmd a -> IO a
continueIO (PutChar c) = putChar c
continueIO GetChar = getChar
以下是此示例的使用情况:
echoChar :: (Monad m) => ContT r m (Cmd a)
echoChar = ContT $ \k -> do
c <- k GetChar
k (PutChar c)
它应该像runContT echoChar continueIO
一样运行。然而,PutChar
和GetChar
命令在它们的类型中发生冲突。如何从同一个ContT发送这两种类型?
附:对不起,如果这个问题中的任何内容都是笨拙的措辞。我想在这里给自己一个挑战,我并不完全明白我在做什么。
编辑:我的解决方案不受限制,我不必使用ContT
。
您的命令都需要是返回相同类型的闭包(例如IO ()
,在这种情况下您不能执行getChar
)或者您需要具有可以容纳IO ()
或IO Char
的多态结果类型,并且ContinueIO
需要采取这是它的论点。然后你需要决定当你将IO Char
传递给GetChar
或者没有传递给PutChar
时会发生什么。 (这个版本可能是Monoid
与<> = ContinueIO
和mempty = id
,然后你可以foldMap
任何Foldable
结构。)