我们经常在haskell中看到=
,<-
,<=
。它们之间的区别是什么?
答案 0 :(得分:10)
=
表示定义为相等。即,如果我写
x = 5
在文件的某个地方,我可以在任何其他点(在同一范围内)将5
替换为x
,反之亦然 - 它们是相同的。 (并且将始终保持不变。)然而,定义也可以引用您绑定它的名称,以提供递归计算,如
fibonacci :: [Integer]
fibonacci = 0 : 1 : zipWith (+) fibs (tail fibonacci)
在这种情况下,您仍然可以随时用fibonacci
替换0 : 1 : zipWith (+) fibs (tail fibonacci)
,但当然您需要无限重复此过程。
=
定义既可以位于顶层,也可以位于模块中的一行,也可以位于let
或where
块中:
silly :: Integer -> Integer
silly x = y
where y = let z = x + 1
in z - 1
此处,silly
是顶级绑定(带有函数参数),y
是where
绑定,z
是let
结合。
<-
表示定义为的结果,表示monadic计算的结果。它通常位于do
块中,例如:
main :: IO ()
main = do
putStrLn "Enter your name, please"
userName <- getLine
putStrLn $ "Hello, " ++ userName
请注意,这与
非常不同main = do
putStrLn "Enter your name, please"
let userName' = getLine
putStrLn $ "Hello, " ++ userName' -- error here
这样做不会将userName
定义为用户输入的字符串,而是定义请求输入字符串的操作。 userName
是String
,但userName' :: IO String
。
<-
也用于列表推导:
squareNums :: [Integer]
squareNums = [x^2 | x <- [0..]]
这似乎与userName <- getLine
有所不同,但实际上它只是在不同的monad(列表而不是IO)中执行相同的操作。事实上我也可以把它写成
squareNums = do
x <- [0..]
return $ x^2
还有<-
的第三种用法,它实际上是不同的:pattern guards,但这些并不常见。
<=
只是一个库函数(以中缀运算符的形式)。对于你在Haskell中遇到的大多数其他符号“语法”也是如此。您可以ask Hayoo关于此类运算符,它会告诉您<=
是defined in the Data.Ord
module,并且只是比较小或相等的比较运算符。
您也可以自己定义这些操作符 - 如果它不在标准库中,我可以轻松定义
(<=) :: Ord a => a -> a -> Bool
x <= y = not $ x > y
顺便提一下,签名中的=>
是完全不同的 - 这又是内置语法。本周还有question about that。
答案 1 :(得分:5)
=
是一种约束力。它将名称绑定到值/表达式。您可以将它用于顶级绑定,let块和块。
myfun x = let y = x + 1
in z y
where z n = n * n
<-
是一个monadic提取。它是do
表示法的一部分,并引入了一个与monad内容绑定的名称。
main = do
name <- getLine
putStrLn ("Hello, " ++ name)
<=
是Cmp
类型类中定义的次要或不相等的运算符。
message x = if x < 18 then "No, you can't vote." else "Go ahead."