我很难理解这一点.写入符号时,以下两行有何不同?
1. let x = expression
2. x <- expression
Run Code Online (Sandbox Code Playgroud)
我看不出来.有时一个工作,有时一个工作.但两者都很少."了解你是一个哈克尔"说,<-右侧将符号绑定在左侧的符号上.但这与简单定义x有let什么不同?
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,其中m是do块所在的IOmonad.例如,在monad中,此表单的绑定必须IO a在右侧具有某种类型的值.该a(所述一元值内)的部分是什么被绑定到在左侧的图案.这使您可以在do块的有限范围内提取monad的"内容" .
该do符号,正如你可能已经读过,只是语法糖在一元绑定运营商(>>=和>>).x <- expression去糖expression >>= \x ->和去糖(和expression它本身,没有<-)去糖expression >>.这只是为定义monadic计算的长链提供了一种更方便的语法,否则它往往会构建一个相当令人印象深刻的嵌套lambda.
let绑定根本不会脱糖,真的.唯一的区别let在do块和let外部的do块是该do版本不需要in关键字遵循它; 它绑定的名称隐含在do块的其余部分的范围内.
在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)
| 归档时间: |
|
| 查看次数: |
4161 次 |
| 最近记录: |