【问题标题】:How to dispatch different types from a ContT?如何从一个联系人中分派不同的类型?
【发布时间】:2018-06-14 19:25:09
【问题描述】:

我想创建一个基于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 之类的东西运行。但是,PutCharGetChar 命令的类型存在冲突。如何从同一个 ContT 分派这两种类型?

附:抱歉,如果这个问题中的任何内容措辞尴尬。我想在这里给自己一个挑战,但我不完全明白我在做什么。

编辑:我的解决方案不受限制,也不必使用ContT

【问题讨论】:

  • 您是否仅限在此处使用ContT?这正是 FreeOperational 旨在处理的那种情况。
  • @Carl 我完全不受限制,我绝对愿意探索这些解决方案。谢谢!
  • @Carl,我认为FT Cmd mFree Cmd 更有可能。
  • 您可能需要一个存在包装器。不过,很难理解您是否真的需要它。

标签: haskell monads monad-transformers continuations continuation-passing


【解决方案1】:

要么你的命令都需要是返回相同类型的闭包(例如IO (),在这种情况下你不能做getChar),或者你需要一个多态的结果类型可以容纳@987654323 @ 或IO CharContinueIO 需要将此作为参数。然后你需要决定当你将IO Char 传递给GetChar 或什么都不传递给PutChar 时会发生什么。 (这个版本可以是Monoid&lt;&gt; = ContinueIOmempty = id,然后你可以在任何Foldable 结构上使用foldMap。)

【讨论】:

  • 有了多态结果类型,延续怎么知道要返回什么?
  • 必须为每种情况定义。 GetChar 将返回一个 Char 包裹在一个 IO Result 或任何你叫它的东西中,PutChar 将返回 ()。他们会调用不同的构造函数。
  • 你也可以做一个更复杂的 AST,其中 GetChar 节点有一个子节点,类型系统只会让你填充以 IO Char 作为输入的东西,如果你想忽略结果,你输入一个ignore-a-Char命令作为终端节点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-01
相关资源
最近更新 更多