简体   繁体   中英

What do 'let' and 'in' mean in Haskell?

I feel like this seemingly simple and essential thing is completely cryptic to me. What does 'let' expression mean? I have tried to google, but the results are full of concepts that I don't understand.

Here is some code I wrote during a lecture. It identifies if a given string is a palindrome. I don't quite understand where the return keyword is either. Is it the 'in'? What is the scope of this function? I am at a loss.

module Main where

isPalindrome :: Text -> Bool
isPalindrome text1 
  = let
    list = toString text1
    backwards = reverse list
    in list == backwards

What does 'in' mean, when it comes after 'let'?

I come from learning C#, and functional programming is unknown to me.

Thank you.

A let -block allows you to create local variables. The general form is

let
  var1 = expression
  var2 = another expression
  var3 = stuff
in
  result expression

The result of this is whatever result expression is, but you can use var1 , var2 and var3 inside result expression (and inside expression , another expression , and stuff as well). You can think of let and in as being brackets around the bunch of local variables you want to define. And yes, the thing after in is what you're returning.

Let's look at an example using IO , as that's more like the imperative languages you're used to:

main :: IO ()
main = do
   let n = 37
   print n

Should be easy enough, right? let n = 37 introduces a local variable called n , giving it the value 37 . That variable can then be used like any global definition. This is basically the same as var n = 37; or int n = 37; in C#.

But Haskell is not an imperative language, so what looks like “do this, then do that” is actually just syntactic sugar for something purely functional. In this example, the do block desugars to something looking very similar:

main = let n = 37
       in print n

The difference, and advantage, is that the variable is not introduced at some point in time as it were, which means you need to be careful about the exact order in which you do stuff, but rather it is introduced into a concrete scope . The scope of a let -bound variable includes everything that comes after the in , but also anything in the let -block itself, meaning you could also have

main = let m = n + 2
           n = 37
       in print m

(note the “reverse control flow”) or even recursive definitions

main = let l = 1 : m
           m = 2 : l
       in print $ take 15 l

(the latter will print [1,2,1,2,1,2,1,2,1,2,1,2,1] )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM