用符号表示"< - "绑定

Und*_*ren 22 binding haskell

我很难理解这一点.写入符号时,以下两行有何不同?

1. let x = expression
2. x <- expression
Run Code Online (Sandbox Code Playgroud)

我看不出来.有时一个工作,有时一个工作.但两者都很少."了解你是一个哈克尔"说,<-右侧将符号绑定在左侧的符号上.但这与简单定义xlet什么不同?

Die*_*Epp 25

<-语句将从monad中提取值,而let语句则不会.

import Data.Typeable

readInt :: String -> IO Int
readInt s = do
  putStrLn $ "Enter value for " ++ s ++ ": "
  readLn

main = do
  x <- readInt "x"
  let y = readInt "y"
  putStrLn $ "x :: " ++ show (typeOf x)
  putStrLn $ "y :: " ++ show (typeOf y)
Run Code Online (Sandbox Code Playgroud)

运行时,程序将询问x的值,因为monadic操作readInt "x"<-语句执行.它不会询问y的值,因为readInt "y"会对其进行求值,但不会执行生成的monadic操作.

Enter value for x: 
123
x :: Int
y :: IO Int

既然如此x :: Int,你可以Int用它做正常的事情.

putStrLn $ "x = " ++ show x
putStrLn $ "x * 2 = " ++ show (x * 2)
Run Code Online (Sandbox Code Playgroud)

既然如此y :: IO Int,你不能假装它是常规的Int.

putStrLn $ "y = " ++ show y -- ERROR
putStrLn $ "y * 2 = " ++ show (y * 2) -- ERROR
Run Code Online (Sandbox Code Playgroud)


bit*_*ket 13

let绑定中,表达式可以具有任何类型,您所做的只是为其命名(或在其内部结构上匹配模式).

<-版本中,表达式必须具有类型m a,其中mdo块所在的IOmonad.例如,在monad中,此表单的绑定必须IO a在右侧具有某种类型的值.该a(所述一元值内)的部分是什么被绑定到在左侧的图案.这使您可以在do块的有限范围内提取monad的"内容" .

do符号,正如你可能已经读过,只是语法糖在一元绑定运营商(>>=>>).x <- expression去糖expression >>= \x ->和去糖(和expression它本身,没有<-)去糖expression >>.这只是为定义monadic计算的长链提供了一种更方便的语法,否则它往往会构建一个相当令人印象深刻的嵌套lambda.

let绑定根本不会脱糖,真的.唯一的区别letdo块和let外部的do块是该do版本不需要in关键字遵循它; 它绑定的名称隐含在do块的其余部分的范围内.


Jer*_*ock 9

let形式中,expressiona是非monadic值,而a的右侧<-是monadic表达式.例如,您只能IO t在第二种绑定中进行I/O操作(类型).详细地说,这两种形式可以大致翻译为(其中==>显示翻译):

do {let x = expression; rest} ==> let x = expression in do {rest}
Run Code Online (Sandbox Code Playgroud)

do {x <- operation; rest} ==> operation >>= (\ x -> do {rest})
Run Code Online (Sandbox Code Playgroud)