ฉันใหม่เพื่อ Haskell และฉันสับสนมากจากไหนเมื่อเทียบกับLet ดูเหมือนทั้งสองจะมีจุดประสงค์ที่คล้ายกัน ฉันได้อ่านการเปรียบเทียบเล็กน้อยระหว่างWhereกับLetแต่ฉันมีปัญหาในการแยกแยะว่าเมื่อใดควรใช้ ใครช่วยกรุณาให้บริบทบางอย่างหรืออาจเป็นตัวอย่างบางส่วนที่แสดงให้เห็นว่าเมื่อใดควรใช้อย่างอื่น
ที่ไหนเทียบกับ
where
ประโยคสามารถกำหนดเฉพาะในระดับของการกำหนดฟังก์ชั่น โดยปกติแล้วจะเหมือนกับขอบเขตของlet
คำจำกัดความ ความแตกต่างเพียงอย่างเดียวคือเมื่อยามที่มีการใช้ ขอบเขตของwhere
ประโยคขยายครอบคลุมยามทั้งหมด ในทางตรงกันข้ามขอบเขตของlet
นิพจน์เป็นเพียงประโยคฟังก์ชันปัจจุบันและตัวป้องกันถ้ามี
Haskell วิกิพีเดียมีรายละเอียดมากและให้หลาย ๆ กรณี แต่จะใช้ตัวอย่างสมมุติ ฉันพบว่าคำอธิบายสั้นเกินไปสำหรับผู้เริ่มต้น
ข้อดีของการให้ :
f :: State s a
f = State $ \x -> y
where y = ... x ...
จะไม่ทำงานเนื่องจากโดยที่อ้างถึงรูปแบบที่ตรงกับ f = โดยที่ x ไม่อยู่ในขอบเขต ในทางตรงกันข้ามถ้าคุณเริ่มต้นด้วยการปล่อยให้คุณก็จะไม่มีปัญหา
Haskell Wiki เกี่ยวกับข้อดีของการให้
f :: State s a
f = State $ \x ->
let y = ... x ...
in y
ข้อดีของที่ไหน :
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)
วิกิฮาสเคลกล่าวว่าประโยค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 "
ให้นิพจน์
นิพจน์ let ของ Haskell มีประโยชน์เมื่อใดก็ตามที่จำเป็นต้องใช้ชุดการผูกที่ซ้อนกัน เป็นตัวอย่างง่ายๆให้พิจารณา:
let y = a*b f x = (x+y)/y in f c + f d
ชุดของการผูกที่สร้างขึ้นโดยนิพจน์ let นั้นเป็นแบบวนซ้ำร่วมกันและการผูกรูปแบบจะถือว่าเป็นรูปแบบที่ขี้เกียจ (กล่าวคือมีนัย ~) การประกาศประเภทเดียวที่อนุญาตคือลายเซ็นประเภทการผูกฟังก์ชันและการผูกรูปแบบ
ที่ข้อ
บางครั้งมันก็สะดวกในการกำหนดขอบเขตการผูกกับสมการที่มีการป้องกันหลาย ๆ อย่างซึ่งต้องใช้คำสั่ง where:
f x y | y>z = ... | y==z = ... | y<z = ... where z = x*x
โปรดทราบว่าสิ่งนี้ไม่สามารถทำได้ด้วยนิพจน์ let ซึ่งขอบเขตเหนือนิพจน์ที่ล้อมรอบเท่านั้น โดยที่อนุประโยคได้รับอนุญาตที่ระดับบนสุดของชุดสมการหรือนิพจน์กรณีเท่านั้น คุณสมบัติและข้อ จำกัด เดียวกันในการผูกในนิพจน์ let ใช้กับคุณสมบัติที่อยู่ในส่วนคำสั่ง ขอบเขตที่ซ้อนกันทั้งสองรูปแบบนี้ดูคล้ายกันมาก แต่จำไว้ว่านิพจน์ let เป็นนิพจน์ในขณะที่ส่วนคำสั่งไม่ใช่ - เป็นส่วนหนึ่งของไวยากรณ์ของการประกาศฟังก์ชันและนิพจน์กรณี
f = body where x = xbody; y = ybody ...
หมายถึงf = let x = xbody; y = ybody ... in body
case .... of ... where
นิพจน์ได้หรือไม่? ฉันไม่แน่ใจเกี่ยวกับเรื่องนี้
let
และwhere
เมื่อฉันเริ่มเรียนรู้ Haskell ครั้งแรก ฉันคิดว่าวิธีที่ดีที่สุดในการทำความเข้าใจคือการตระหนักว่าทั้งสองมีความแตกต่างกันเล็กน้อยดังนั้นจึงไม่มีอะไรต้องกังวล ความหมายของการwhere
ให้ในแง่ของlet
การแปลงทางกลที่เรียบง่ายมาก ดูhaskell.org/onlinereport/decls.html#sect4.4.3.2 การ เปลี่ยนแปลงนี้มีขึ้นเพื่อความสะดวกในการระบุเท่านั้นจริงๆ