Haskell: Where vs. Let

前端 未结 5 1659
余生分开走
余生分开走 2020-12-02 04:56

I am new to Haskell and I am very confused by Where vs. Let. They both seem to provide a similar purpose. I have read a few comparisons bet

相关标签:
5条回答
  • 2020-12-02 05:11

    Sadly, most of the answers here are too technical for a beginner.

    LHYFGG has a relevant chapter on it -which you should read if you haven't already, but in essence:

    • where is just a syntactic construct (not a sugar) that are useful only at function definitions.
    • let ... in is an expression itself, thus you can use them wherever you can put an expression. Being an expression itself, it cannot be used for binding things for guards.

    Lastly, you can use let in list comprehensions too:

    calcBmis :: (RealFloat a) => [(a, a)] -> [a]
    calcBmis xs = [bmi | (w, h) <- xs, let bmi = w / h ^ 2, bmi >= 25.0]
    -- w: width
    -- h: height
    

    We include a let inside a list comprehension much like we would a predicate, only it doesn't filter the list, it only binds to names. The names defined in a let inside a list comprehension are visible to the output function (the part before the |) and all predicates and sections that come after of the binding. So we could make our function return only the BMIs of people >= 25:

    0 讨论(0)
  • 2020-12-02 05:24

    I found this example from LYHFGG helpful:

    ghci> 4 * (let a = 9 in a + 1) + 2  
    42  
    

    let is an expression so you can put a let anywhere(!) where expressions can go.

    In other words, in the example above it is not possible to use where to simply replace let (without perhaps using some more verbose case expression combined with where).

    0 讨论(0)
  • 2020-12-02 05:25

    While there is the technical difference with respect to guards that ephemient pointed out, there is also a conceptual difference in whether you want to put the main formula upfront with extra variables defined below (where) or whether you want to define everything upfront and put the formula below (let). Each style has a different emphasis and you see both used in math papers, textbooks, etc. Generally, variables that are sufficiently unintuitive that the formula doesn't make sense without them should be defined above; variables that are intuitive due to context or their names should be defined below. For example, in ephemient's hasVowel example, the meaning of vowels is obvious and so it need not be defined above its usage (disregarding the fact that let wouldn't work due to the guard).

    0 讨论(0)
  • 2020-12-02 05:25

    Legal:

    main = print (1 + (let i = 10 in 2 * i + 1))
    

    Not legal:

    main = print (1 + (2 * i + 1 where i = 10))
    

    Legal:

    hasVowel [] = False
    hasVowel (x:xs)
      | x `elem` vowels = True
      | otherwise = False
      where vowels = "AEIOUaeiou"
    

    Not legal: (unlike ML)

    let vowels = "AEIOUaeiou"
    in hasVowel = ...
    
    0 讨论(0)
  • 2020-12-02 05:30

    1: The problem in the example

    f :: State s a
    f = State $ \x -> y
        where y = ... x ...
    

    is the parameter x. Things in the where clause can refer only to the parameters of the function f (there are none) and things in outer scopes.

    2: To use a where in the first example, you can introduce a second named function that takes the x as a parameter, like this:

    f = State f'
    f' x = y
        where y = ... x ...
    

    or like this:

    f = State f'
        where
        f' x = y
            where y = ... x ...
    

    3: Here is a complete example without the ...'s:

    module StateExample where
    
    data State a s = State (s -> (a, s))
    
    f1 :: State Int (Int, Int)
    f1 = State $ \state@(a, b) ->
        let
            hypot = a^2 + b^2
            result = (hypot, state)
        in result
    
    f2 :: State Int (Int, Int)
    f2 = State f
        where
        f state@(a, b) = result
            where
            hypot = a^2 + b^2
            result = (hypot, state)
    

    4: When to use let or where is a matter of taste. I use let to emphasize a computation (by moving it to the front) and where to emphasize the program flow (by moving the computation to the back).

    0 讨论(0)
提交回复
热议问题