ฉันเจอคำจำกัดความต่อไปนี้เมื่อฉันพยายามเรียนรู้ Haskell โดยใช้โครงการจริงเพื่อผลักดันมัน ฉันไม่เข้าใจว่าเครื่องหมายอัศเจรีย์หน้าแต่ละอาร์กิวเมนต์หมายถึงอะไรและหนังสือของฉันไม่ได้พูดถึงมัน
data MidiMessage = MidiMessage !Int !MidiMessage
ฉันเจอคำจำกัดความต่อไปนี้เมื่อฉันพยายามเรียนรู้ Haskell โดยใช้โครงการจริงเพื่อผลักดันมัน ฉันไม่เข้าใจว่าเครื่องหมายอัศเจรีย์หน้าแต่ละอาร์กิวเมนต์หมายถึงอะไรและหนังสือของฉันไม่ได้พูดถึงมัน
data MidiMessage = MidiMessage !Int !MidiMessage
คำตอบ:
มันเป็นการประกาศความเข้มงวด โดยทั่วไปหมายความว่าจะต้องประเมินสิ่งที่เรียกว่า "รูปแบบปกติที่อ่อนแอของหัว" เมื่อค่าโครงสร้างข้อมูลถูกสร้างขึ้น ลองดูตัวอย่างเพื่อที่เราจะได้เห็นความหมายของสิ่งนี้:
data Foo = Foo Int Int !Int !(Maybe Int)
f = Foo (2+2) (3+3) (4+4) (Just (5+5))
ฟังก์ชั่นf
ด้านบนเมื่อประเมินแล้วจะคืนค่า "thunk": นั่นคือรหัสที่เรียกใช้งานเพื่อหาค่าของมัน ณ จุดนี้ฟูยังไม่มีแม้แต่เพียงแค่รหัส
แต่เมื่อถึงจุดหนึ่งบางคนอาจลองมองเข้าไปข้างในอาจผ่านการจับคู่รูปแบบ:
case f of
Foo 0 _ _ _ -> "first arg is zero"
_ -> "first arge is something else"
นี่เป็นการเรียกใช้งานรหัสที่เพียงพอเพื่อทำสิ่งที่ต้องการและไม่ต้องทำอีกต่อไป ดังนั้นมันจะสร้าง Foo ที่มีสี่พารามิเตอร์ (เพราะคุณไม่สามารถดูข้างในได้หากไม่มีมัน) ข้อแรกเนื่องจากเราทำการทดสอบเราจำเป็นต้องประเมินทุกวิถีทางเพื่อ4
ที่เราจะได้รู้ว่ามันไม่ตรงกัน
ข้อที่สองไม่จำเป็นต้องประเมินเพราะเราไม่ได้ทำการทดสอบ ดังนั้นแทนที่จะถูกเก็บไว้ในสถานที่ตั้งของหน่วยความจำที่เราจะเก็บเพียงรหัสสำหรับการประเมินผลภายหลังเป็นไปได้6
(3+3)
ที่จะกลายเป็น 6 เท่านั้นถ้ามีคนมองไปที่มัน
อย่างไรก็ตามพารามิเตอร์ที่สามมี!
ส่วนหน้าของมันดังนั้นจะถูกประเมินอย่างเข้มงวด: (4+4)
ถูกเรียกใช้และ8
ถูกเก็บไว้ในตำแหน่งหน่วยความจำนั้น
พารามิเตอร์ที่สี่ยังถูกประเมินอย่างเคร่งครัด แต่นี่คือจุดที่มันค่อนข้างยุ่งยาก: เรากำลังประเมินไม่เต็มที่ แต่จะอยู่ในรูปหัวปกติที่อ่อนแอเท่านั้น นี่หมายความว่าเรารู้ว่ามันเป็นอะไรNothing
หรือJust
เปล่าแล้วเก็บมันไว้ แต่เราไม่ไปไกลกว่านี้ นั่นหมายความว่าเราไม่ได้เก็บJust 10
แต่จริง ๆ แล้วJust (5+5)
ปล่อยให้อันธพาลข้างในไม่ได้ประเมินค่า สิ่งนี้เป็นสิ่งสำคัญที่ต้องรู้แม้ว่าฉันคิดว่าความหมายทั้งหมดของสิ่งนี้จะไปไกลเกินขอบเขตของคำถามนี้
คุณสามารถใส่คำอธิบายประกอบอาร์กิวเมนต์ของฟังก์ชั่นในลักษณะเดียวกันหากคุณเปิดใช้งานBangPatterns
ส่วนขยายภาษา:
f x !y = x*y
f (1+1) (2+2)
จะกลับ (1+1)*4
thunk
seq
แต่ผมไม่ได้กล่าวถึงรูปแบบปังหรือคำอธิบายประกอบเข้มงวดพวกเขาจะเทียบเท่ากับการใช้
วิธีง่ายๆในการดูความแตกต่างระหว่างอาร์กิวเมนต์ตัวสร้างแบบเข้มงวดและแบบไม่ จำกัด คือวิธีการทำงานเมื่อไม่ได้กำหนด ป.ร. ให้ไว้
data Foo = Foo Int !Int
first (Foo x _) = x
second (Foo _ y) = y
เนื่องจากข้อโต้แย้งที่ไม่เข้มงวดไม่ได้รับการประเมินโดยการsecond
ส่งผ่านundefined
จึงไม่ทำให้เกิดปัญหา:
> second (Foo undefined 1)
1
แต่อาร์กิวเมนต์ที่เข้มงวดไม่สามารถทำได้undefined
แม้ว่าเราจะไม่ใช้ค่า:
> first (Foo 1 undefined)
*** Exception: Prelude.undefined
!
สัญลักษณ์ที่มีอยู่แทนที่จะเจาะลึกลงไปในรายละเอียดการใช้งานภายใน
ฉันเชื่อว่ามันเป็นคำอธิบายประกอบที่เข้มงวด
Haskell เป็นภาษาที่ใช้งานได้ดีและขี้เกียจแต่บางครั้งค่าโสหุ้ยในการขี้เกียจอาจมากเกินไปหรือสิ้นเปลือง ดังนั้นเพื่อจัดการกับสิ่งนั้นคุณสามารถขอให้คอมไพเลอร์ประเมินค่าอาร์กิวเมนต์ทั้งหมดของฟังก์ชันแทนที่จะแยกวิเคราะห์รอบ ๆ
มีข้อมูลเพิ่มเติมเกี่ยวกับหน้านี้เป็น: ผลการดำเนินงาน / เข้มงวด
map Just [1,2,3]
เพื่อรับ [เพียงแค่ 1 แค่ 2 เพียงแค่ 3]) และอื่น ๆ ฉันคิดว่ามันมีประโยชน์ที่จะคิดว่าความสามารถในการจับคู่รูปแบบกับพวกเขารวมถึงสิ่งอำนวยความสะดวกที่ไม่เกี่ยวข้องอย่างสมบูรณ์