< - 和" let"之间有什么区别?在里面做块?

时间:2016-02-29 12:23:49

标签: haskell frege

我不知道何时必须使用let以及何时必须使用<-绑定。

3 个答案:

答案 0 :(得分:4)

let给出函数调用结果的名称。

<-将当前monad中monadic操作的结果绑定到名称。

他们完全不同。使用let作为monad之外的函数的结果,即普通的纯函数。使用<-表示任何monadic,因为它“解包”monad结果并让你获得其中的值。

例如:

假设具有以下签名的IO功能

frobnicate :: String -> IO Bool

和纯函数

dothing :: Bool -> Bool

我们可以这样做

main :: IO ()
main = do
  x <- frobnicate "Hello"
  let y = frobnicate "Hello"
  -- z <- dothing x
  let z = dothing x
  return ()

我们知道x :: Bool,因为Bool已从我们的IO操作结果中提取(操作运行,结果称为x所以我们可以在以后使用它。)

我们也知道y :: IO Bool - 操作尚未运行,它是未来IO操作的潜力。因此,我们可以使用y执行唯一有用的操作是稍后运行,绑定结果并以Bool内部方式获取,但let Bool之后甚至还存在。

第三行被注释掉,因为它不会编译 - 你不能对不在相关monad中的操作进行monadic绑定。 dothing不会返回IO任何内容,因此您无法将其绑定到IO ()函数中。

第四行很简单 - zdothing x的结果,其中x是从先前运行frobnicate "Hello"解包的值。

所有这些只是下面“真正的”monad操作的语法糖,因此扩展(没有注释部分)类似

main = frobnicate "Hello" >>= (\x -> let y = frobnicate "Hello"
                                         z = dothing x
                                      in return ())

这个例子当然没有任何意义,但希望它能说明let<-do符号中的区别。

TL; DR:使用<-为monadic操作的结果命名,let为其他所有操作命名。

答案 1 :(得分:3)

public function boot(Factory $validator) { require_once app_path() . '/validators.php'; } <->>=),其中bind位于let块中的fmap

here窃取示例:

do

do x1 <- action1 x0 x2 <- action2 x1 action3 x1 x2 -- is equivalent to: action1 x0 >>= \ x1 -> action2 x1 >>= \ x2 -> action3 x1 x2 action1&amp; action2都返回某种monad,比如说:

action3

您可以重写let绑定:

action1 :: (Monad m) => a -> m b
action2 :: (Monad m) => b -> m c
action3 :: (Monad m) => b -> c -> m d

答案 2 :(得分:1)

可视化<-的作用的一个很好的例子:

do
    a <- ['a'..'z']
    b <- [1..3]
    pure (a,b)

您可以在try.frege-lang.org的在线REPL中尝试此操作 (您可以将其输入为单行:

do { a <- ['a'..'z']; b <- [1..3]; pure (a,b) }