Haskell : Where vs. Let
나는 Haskell을 처음 접했고 Where vs. Let에 대해 매우 혼란 스럽습니다 . 둘 다 비슷한 목적을 제공하는 것 같습니다. Where 와 Let 사이의 몇 가지 비교를 읽었 지만 언제 각각을 사용해야하는지 구분하는 데 어려움이 있습니다. 누군가가 컨텍스트를 제공하거나 다른 것을 사용할 때를 보여주는 몇 가지 예를 제공 할 수 있습니까?
어디 대하자
where
절은 함수 정의의 수준에서 정의 할 수 있습니다. 일반적으로let
정의 범위와 동일합니다 . 유일한 차이점은 가드를 사용할 때 입니다.where
절의 범위는 모든 가드에 걸쳐 있습니다. 반대로let
표현식 의 범위 는 현재 함수 절과 가드 (있는 경우)뿐입니다.
하스켈 위키는 매우 상세하고 다양한 사례를 제공하지만 가상의 예를 사용합니다. 초보자에게는 설명이 너무 짧습니다.
Let의 장점 :
f :: State s a
f = State $ \x -> y
where y = ... x ...
where는 f = 일치하는 패턴을 나타내므로 작동하지 않습니다. 여기서 x는 범위에 없습니다. 반대로 let으로 시작했다면 문제가 없을 것입니다.
f :: State s a
f = State $ \x ->
let y = ... x ...
in y
Where의 장점 :
f x
| cond1 x = a
| cond2 x = g a
| otherwise = f (h x a)
where
a = w x
f x
= let a = w x
in case () of
_ | cond1 x = a
| cond2 x = g a
| otherwise = f (h x a)
Haskell wiki는 Where 절이 선언적이지만 Let 표현식은 표현 적이 라고 언급합니다 . 스타일 외에도 어떻게 다르게 수행합니까?
Declaration style | Expression-style
--------------------------------------+---------------------------------------------
where clause | let expression
arguments LHS: f x = x*x | Lambda abstraction: f = \x -> x*x
Pattern matching: f [] = 0 | case expression: f xs = case xs of [] -> 0
Guards: f [x] | x>0 = 'a' | if expression: f [x] = if x>0 then 'a' else ...
- 첫 번째 예에서 Let 은 범위에 있지만 어디에 있지 않습니까?
- 첫 번째 예에 Where 를 적용 할 수 있습니까 ?
- 변수가 실제 표현을 나타내는 실제 예제에 이것을 적용 할 수 있습니까?
- 각각을 사용할 때 따라야 할 일반적인 경험 법칙이 있습니까?
최신 정보
나중에이 스레드에서 오는 사람들을 위해 여기에서 찾을 수있는 최상의 설명을 찾았습니다 : " A Gentle Introduction to Haskell ".
식하자.
Haskell의 let 표현식은 중첩 된 바인딩 세트가 필요할 때 유용합니다. 간단한 예로서 다음을 고려하십시오.
let y = a*b f x = (x+y)/y in f c + f d
let 표현식에 의해 생성 된 바인딩 세트는 상호 재귀 적이며 패턴 바인딩은 지연 패턴으로 처리됩니다 (즉, 암시 적 ~을 전달 함). 허용되는 유일한 선언 유형은 형식 서명, 함수 바인딩 및 패턴 바인딩입니다.
Where 절.
Sometimes it is convenient to scope bindings over several guarded equations, which requires a where clause:
f x y | y>z = ... | y==z = ... | y<z = ... where z = x*x
Note that this cannot be done with a let expression, which only scopes over the expression which it encloses. A where clause is only allowed at the top level of a set of equations or case expression. The same properties and constraints on bindings in let expressions apply to those in where clauses. These two forms of nested scope seem very similar, but remember that a let expression is an expression, whereas a where clause is not -- it is part of the syntax of function declarations and case expressions.
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).
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).
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 = ...
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
).
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:
참고URL : https://stackoverflow.com/questions/4362328/haskell-where-vs-let
'developer tip' 카테고리의 다른 글
파이썬에서 부울을 어떻게 사용합니까? (0) | 2020.08.11 |
---|---|
Rails 3에서 마이그레이션 파일을 삭제하는 방법 (0) | 2020.08.11 |
만드는 방법 (0) | 2020.08.10 |
Java의 Thread.sleep은 언제 InterruptedException을 발생합니까? (0) | 2020.08.10 |
유니 코드 문자를 URL 인코딩하는 올바른 방법은 무엇입니까? (0) | 2020.08.10 |