【问题标题】:Types and do notation类型和 do 表示法
【发布时间】:2013-05-15 19:26:22
【问题描述】:

这是几个问题合而为一:

  1. do 表示法中,每一行是否必须返回相同的类型?例如,我可以在返回 IO monad 的单个 do 块中写一行,而另一行返回一个整数? (我的理解是,基于 >>>>= 的脱糖似乎如何起作用,答案是否定的。)

  2. 如果不是,那么编译器如何确定这些行都必须返回什么类型?在我看到的所有示例中,作者都​​认为我们只是在使用IO monads。但是你怎么知道,对于给定的do 块,每一行必须返回什么?

  3. 再次假设#1 的答案是否定的:如何在do 块内使用不返回正确类型的monad 的函数?例如,考虑这个 websockets 代码:

    application :: MVar ServerState -> WS.Request -> WS.WebSockets WS.Hybi00 ()
    application state rq = do
      WS.acceptRequest rq
      msg <- WS.receiveData :: WS.WebSockets WS.Hybi00 Text
      return ()
    

    假设我想打印msg 的值。我将如何以不与 do 块的类型冲突的方式进行处理?

【问题讨论】:

  • 你为什么不试试呢?此外,由于 do-notation 只是语法糖(正如您所说。翻译成 (&gt;&gt;=)(&gt;&gt;))手头的机制与任何其他类型类完全相同,而不是特定于 do-notation 和 @ 987654334@s.
  • 抱歉,我上次编辑时不小心弄乱了代码格式(引入了枚举)。不幸的是,我的更正字符太少而不能作为编辑。请您再解决一下这个问题吗?
  • 是的,我修好了。我看到您如何尝试使用 Markdown 编号列表,但它们似乎与代码块冲突。这就是为什么我选择将每个数字放在自己的段落中。
  • 我认为,您必须将代码块再缩进 4 个空格(即总共 8 个空格)才能使其在枚举中工作。

标签: haskell monads


【解决方案1】:
  1. 在一个do-block中,每一行可以返回不同的类型,但它们必须在同一个monad中
    • 一行可以返回IO String,另一行可以返回IO Integer,但它们都必须是IO
  2. 与 Haskell 的其余部分相同。类型推断。就像在 Haskell 的其他部分中一样,它并不总是有效,如果无效,您也必须进行注释。
  3. 有两种方法可以做到这一点
    • let,记住在 GHCi 中你必须使用 let 声明局部变量,你可以在 do 块中做同样的事情。 let someMonad = doSomething
      • 注意,没有in
    • Monad 变形金刚!这是一个需要在简介中解释的大话题,但基本上它们是具有特殊功能lift 的单子,可以将另一个单子“提升”到变压器中。变压器通常以 T 结尾,例如 StateT。几乎您使用的每个 monad 都有一个等效的转换器。

【讨论】:

    【解决方案2】:

    要回答你最后一个问题的最后一部分,

    假设我想打印msg 的值。我将如何以不与 do 块的类型冲突的方式来解决这个问题?

    作为jozefg said in his answer,monad 转换器通常是你需要的。但是,在这种情况下,WebSockets p monad 不是转换器。但是,它是 MonadIO 的一个实例,它是 monad 堆栈的一个类,它在“底部”有 IO,因此可以让你在其中运行任意的 IO 动作。

    MonadIO 类提供函数liftIO,其类型为

    liftIO :: MonadIO m => IO a -> m a
    

    在您的情况下,这变为IO a -&gt; WebSockets Hybi00 a,因此您可以使用它将print msg 操作从IO () 转换为WebSockets Hybi00 (),然后您可以在do 块中使用它:

    application :: MVar ServerState -> WS.Request -> WS.WebSockets WS.Hybi00 ()
    application state rq = do
      WS.acceptRequest rq
      msg <- WS.receiveData :: WS.WebSockets WS.Hybi00 Text
      liftIO $ print msg
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-13
      相关资源
      最近更新 更多