โปรดทราบว่า:sprint
จะไม่ลดนิพจน์เป็น WHNF ถ้าเป็นเช่นนั้นแล้วสิ่งต่อไปนี้จะให้4
มากกว่า_
:
Prelude> let four = 2 + 2 :: Int
Prelude> :sprint four
four = _
แต่:sprint
ใช้ชื่อของการผูกไว้ลัดเลาะการเป็นตัวแทนภายในของมูลค่าของการผูกและแสดงให้เห็นถึง "ส่วนที่ได้รับการประเมิน" แล้ว (เช่นชิ้นส่วนที่เป็นผู้สร้าง) ในขณะที่ใช้_
เป็นตัวยึดสำหรับ thunks ประเมินค่า (เช่นฟังก์ชั่นขี้เกียจ โทร) หากค่าไม่ได้รับการประเมินอย่างสมบูรณ์จะไม่มีการประเมินผลใด ๆ แม้แต่ WHNF (และหากประเมินค่าอย่างสมบูรณ์คุณจะได้รับไม่ใช่แค่ WHNF)
สิ่งที่คุณสังเกตในการทดลองของคุณคือการรวมกันของ polymorphic เทียบกับประเภทตัวเลข monomorphic, การเป็นตัวแทนภายในที่แตกต่างกันสำหรับตัวอักษรสตริงและรายชื่อตัวละครที่ชัดเจน ฯลฯ โดยทั่วไปคุณสังเกตความแตกต่างทางเทคนิคในการรวบรวม ดังนั้นการตีความรายละเอียดการติดตั้งเหล่านี้ว่ามีส่วนเกี่ยวข้องกับ WHNF จะทำให้คุณสับสนอย่างสิ้นหวัง โดยทั่วไปคุณควรใช้:sprint
เป็นเครื่องมือดีบั๊กเท่านั้นไม่ใช่วิธีเรียนรู้เกี่ยวกับ WHNF และความหมายของการประเมิน Haskell
หากคุณต้องการเข้าใจสิ่งที่:sprint
กำลังทำจริง ๆ คุณสามารถเปิดการตั้งค่าสถานะบางอย่างใน GHCi เพื่อดูว่ามีการจัดการกับนิพจน์อย่างไรและในที่สุดก็รวบรวมเป็น bytecode:
> :set -ddump-simpl -dsuppress-all -dsuppress-uniques
หลังจากนี้เราจะเห็นเหตุผลที่คุณintlist
ให้_
:
> let intlist = [[1,2],[2,3]]
==================== Simplified expression ====================
returnIO
(: ((\ @ a $dNum ->
: (: (fromInteger $dNum 1) (: (fromInteger $dNum 2) []))
(: (: (fromInteger $dNum 2) (: (fromInteger $dNum 3) [])) []))
`cast` <Co:10>)
[])
คุณสามารถเพิกเฉยต่อreturnIO
และ:
โทรออกและมุ่งเน้นส่วนที่เริ่มต้นด้วย((\ @ a $dNum -> ...
นี่$dNum
คือพจนานุกรมสำหรับNum
ข้อ จำกัด ซึ่งหมายความว่ารหัสที่สร้างขึ้นยังไม่ได้รับการแก้ไขประเภทที่แท้จริงa
ในประเภทNum a => [[a]]
ดังนั้นการแสดงออกทั้งหมดยังคงแสดงว่าเป็นการเรียกใช้ฟังก์ชั่น (พจนานุกรมสำหรับ) Num
ประเภทที่เหมาะสม กล่าวอีกนัยหนึ่งมันเป็นสิ่งที่ไม่ได้ประเมินค่าและเราจะได้รับ:
> :sprint intlist
_
ในอีกทางหนึ่งระบุประเภทเป็นInt
และรหัสแตกต่างอย่างสิ้นเชิง:
> let intlist = [[1::Int,2],[2,3]]
==================== Simplified expression ====================
returnIO
(: ((: (: (I# 1#) (: (I# 2#) []))
(: (: (I# 2#) (: (I# 3#) [])) []))
`cast` <Co:6>)
[])
และ:sprint
ผลลัพธ์ก็คือ:
> :sprint intlist
intlist = [[1,2],[2,3]]
ในทำนองเดียวกันสตริงตัวอักษรและรายการตัวอักษรที่ชัดเจนมีการแสดงที่แตกต่างกันอย่างสมบูรณ์:
> let stringlist = ["hi", "there"]
==================== Simplified expression ====================
returnIO
(: ((: (unpackCString# "hi"#) (: (unpackCString# "there"#) []))
`cast` <Co:6>)
[])
> let charlist = [['h','i'], ['t','h','e','r','e']]
==================== Simplified expression ====================
returnIO
(: ((: (: (C# 'h'#) (: (C# 'i'#) []))
(: (: (C# 't'#)
(: (C# 'h'#) (: (C# 'e'#) (: (C# 'r'#) (: (C# 'e'#) [])))))
[]))
`cast` <Co:6>)
[])
และความแตกต่างในการ:sprint
ส่งออกหมายถึงสิ่งประดิษฐ์ซึ่งเป็นส่วนหนึ่งของการแสดงออก GHCi พิจารณาประเมินผล (อย่างชัดเจน:
ก่อสร้าง) เมื่อเทียบกับ unevaluated (คนunpackCString#
thunks)