Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 类型和do符号_Haskell_Monads - Fatal编程技术网

Haskell 类型和do符号

Haskell 类型和do符号,haskell,monads,Haskell,Monads,这是几个问题合在一起: 在do表示法中,每一行是否必须返回相同的类型?例如,我可以在一个do块中写一行返回IOmonad,另一行返回整数吗?(我的理解是,根据>和>=的脱糖效果,答案是否定的。) 如果不是,那么编译器如何确定行必须全部返回的类型?在我所看到的所有例子中,作者认为我们只是在使用IOmonad,这是一个必然的结论。但是,对于给定的do块,您如何知道每一行必须返回什么 再次假设#1的答案是否定的:如何使用在do块中没有返回正确类型monad的函数?例如,考虑这个WebSoCube代码:

这是几个问题合在一起:

  • do
    表示法中,每一行是否必须返回相同的类型?例如,我可以在一个
    do
    块中写一行返回
    IO
    monad,另一行返回整数吗?(我的理解是,根据
    >
    >=
    的脱糖效果,答案是否定的。)

  • 如果不是,那么编译器如何确定行必须全部返回的类型?在我所看到的所有例子中,作者认为我们只是在使用
    IO
    monad,这是一个必然的结论。但是,对于给定的
    do
    块,您如何知道每一行必须返回什么

  • 再次假设#1的答案是否定的:如何使用在
    do
    块中没有返回正确类型monad的函数?例如,考虑这个WebSoCube代码:

    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 ()
    
    application::MVar ServerState->WS.Request->WS.WebSockets WS.Hybi00()
    应用程序状态rq=do
    WS.AcceptRequestRQ
    味精
    
  • 在do块中,每一行可以返回不同的类型,但它们必须在同一个monad中
    • 一行可以返回
      IO字符串
      ,一行可以返回
      IO整数
      ,但它们都必须是
      IO
  • 和哈斯克尔的其他人一样。类型推断。就像在Haskell的其他部分一样,它并不总是有效的,当它不起作用时,您也必须进行注释
  • 有两种方法可以做到这一点
    • let
      ,记住必须在GHCi中使用let来声明局部变量,您可以在
      do
      块中执行相同的操作<代码>让someMonad=doSomething
    • 注意,在
  • 蒙纳德变形金刚!这是一个很重要的话题,需要在一个简介中解释,但基本上它们是单子,有一个特殊的功能
    lift
    ,可以将另一个单子“提升”到转换器中。变压器通常以T结尾,如StateT。几乎你使用的每个单子都有一个等效的变压器

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

    假设我想打印
    msg
    的值。我将如何以一种和
    do
    块的类型不冲突的方式来实现这一点

    正如你所知,monad transformers通常就是你所需要的。但是,在这种情况下,
    WebSockets p
    monad不是转换器。但是,它是
    MonadIO
    的一个实例,它是monad堆栈的一个类,monad堆栈的
    IO
    “在底部”,因此允许您从内部运行任意
    IO
    操作

    MonadIO
    类提供函数
    liftIO
    ,该函数具有

    liftIO :: MonadIO m => IO a -> m a
    
    在您的情况下,这将成为
    IO a->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
    
    application::MVar ServerState->WS.Request->WS.WebSockets WS.Hybi00()
    应用程序状态rq=do
    WS.AcceptRequestRQ
    
    你为什么不试试呢?此外,由于do表示法只是语法糖(正如您所说,它可以翻译成
    (>>=)
    (>>)
    ),所以手头的机制与任何其他类型类完全相同,并且不特定于do表示法和
    Monad
    s。抱歉,我在上次编辑时不小心弄乱了代码格式(引入了枚举)。不幸的是,我的更正将包含太少的字符,无法作为编辑。请您再次更正,好吗?是的,我已修复。我看到您试图使用标记编号列表,但它们似乎与代码块冲突。这就是为什么我选择将每个数字放在其自己的段落中。您必须将代码块缩进a f我想还有4个空格(总共8个)可以让它在枚举中工作。