は式をWHNFに削減:sprint
しないことに注意してください。もしそうなら、以下はでは4
なく与えるでしょう_
:
Prelude> let four = 2 + 2 :: Int
Prelude> :sprint four
four = _
むしろ、:sprint
バインディングの名前を取り、バインディングの値の内部表現をトラバースし、_
未評価のサンク(つまり、中断された遅延関数)のプレースホルダーとして使用しながら、すでに「評価された部分」(つまり、コンストラクターである部分)を表示します。呼び出し)。値が完全に未評価の場合、評価は行われず、WHNFに対しても行われません。(そして、値が完全に評価されれば、WHNFだけでなく、それも得られます。)
実験で観察しているのは、ポリモーフィック数値型とモノモーフィック数値型の組み合わせ、文字列リテラルと文字の明示的なリストの異なる内部表現などです。基本的に、異なるリテラル式がバイトコードにコンパイルされる方法の技術的な違いを観察しています。したがって、これらの実装の詳細をWHNFと関係があると解釈すると、絶望的に混乱することになります。一般的には、:sprint
WHNFとHaskell評価のセマンティクスについて学ぶ方法としてではなく、デバッグツールとしてのみ。
実際に何:sprint
が行われているのかを理解したい場合は、GHCiでいくつかのフラグをオンにして、式が実際にどのように処理されているかを確認し、最終的にバイトコードにコンパイルすることができます。
> :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
制約の辞書です。これは、生成されたコードがまだtypeの実際の型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が評価された(明示的な:
コンストラクター)と評価されていない(サンク)と見なす式の部分のアーティファクトを表しますunpackCString#
。