let in 的用法 Haskell

The usage of let in Haskell

我在 Haskell 中有此代码。

import Data.List

main = do
    putStrLn $ "\nVerify if Exists in a String"
    let wordlist = ["monad", "monoid", "Galois", "ghc", "SPJ"]
    let tweet = "This is an example tweet talking about SPJ interviewing with Galois"
    print $ map (flip isInfixOf tweet) wordlist

没有 let,我收到此错误消息:10_things.hs:16:14: parse error on input ‘=’

这是另一个运行良好的代码。

import Data.List

wordlist = ["monad", "monoid", "Galois", "ghc", "SPJ"]
tweet = "This is an example tweet talking about SPJ interviewing with Galois"      
main = do
    putStrLn $ "\nVerify if Exists in a String"
    print $ map (flip isInfixOf tweet) wordlist

在这种情况下,我对 let 有错误 parse error (possibly incorrect indentation or mismatched brackets)。 我的问题是何时以及何时不在 Haskell 中使用 let

Haskell有两种引入名字的方式:letwhere

只要你能有一个正常的表达,你就使用let。这可以出现在两个地方:如果你定义一个普通值,如果你在 do-notation 中。在第一种情况下,您可以使用 let ... in 在单个表达式中引入名称:

myFoo = let x = 10 ^ 10 in x + x

内部do-notation,你不需要in;相反,let 像普通的 "statement" 一样占据一行。这是您的第一个示例:

main = do
  let x = something
  ...

引入名称的另一种方法是使用 where 从句,它位于表达式 之外 。程序的顶层——在模块中定义所有全局可见名称的地方——位于 where 块中,这就是为什么你只写 name = expression 而没有 let 的原因。发生这种情况是因为您的模块隐式具有

module Main where

虽然不是你自己写的,但在上面。

您还可以在不同的范围内编写您自己的 where 块,这也让您可以在没有 let:

的情况下定义名称
foo x = ...
  where helperA = something
        helperB = something

Declarations/equations 需要在 letwhere 块内。在模块的顶层不需要 let 的原因是它本身算作一个 where 块,由它的 module 声明开始。不包含显式 module header 的模块获得隐式

module Main (main) where

开头。

顺便说一句,一个缩进的 let 块可以包含多个声明:只要等式垂直排列,您的代码中不需要第二个 let

do notation is for monads. I am guessing you are unclear about monads.

let 内部使用的 do 符号基本上是绑定的。 do 表示法转换为这种形式

do {let x = expression; restofit} ==> let x = expression in do {restofit}

比如这个

do 
 line1 <- getLine            -- executes an action
 line2 <- getLine            -- executes an action
 let joined = line1 ++ line2 -- pure calculation; no action is executed
 return joined

这转换为

let joined = line1 ++ line2 in line1 <-getLine >> line2 <- getLine