s はコンパイル中に効果的に削除されるためnewtype
、サンクはなく、値のみです。を使用して WHNF を要求するとどうなりrseq
ますか? たとえば、
Sum (lengthyComputation :: Int) `using` rseq
は次のようにSum
定義されます
newtype Sum a = Sum { getSum :: a }
評価されるlengthyComputation
かどうか?信頼できるように、どこかに指定/文書化されていますか?
更新:私の疑問をより詳細に説明させてください。直観的に言うと、「newtype
は厳密なので、その WHNF は内部にラップされているものの WHNF であることは明らかです」。しかし、これは非常に不正確な近道であり、その理由はあまり明確ではないと思います。例を挙げましょう:
標準data
型の場合、WHNF は、値の構築に使用されたコンストラクターがわかっている形式として定義できます。たとえば、持っていない場合はseq
、独自に作成できます
seqMaybe :: Maybe a -> b -> b
seqMaybe Nothing = id
seqMaybe _ = id
同様に、任意のdata
型について、そのコンストラクターの 1 つでパターン マッチングを行うだけです。
では取りましょう
newtype Identity a = Identity { runIdentity :: a }
同様のseqIdentity
関数を作成します。
seqIdentity :: Identity a -> b -> b
seqIdentity (Identity _) = id
明らかに、ここで WHNF に強制されるものは何もありません。(結局のところ、どのコンストラクターが使用されたかは常にわかっています。) コンパイル後は、seqIdentity
と同じになりconst id
ます。実際、seqIdentity
内にラップされた値の評価を強制するようなポリモーフィックを作成することはできませんIdentity
! a の WHNF a をnewtype
単純に変更されていない値として定義することができ、それは一貫性があります。では、sに対して WHNF はどのように定義されているnewtype
のでしょうか。それとも、厳密な定義はなく、「中身の WHNF である」という動作は、単純に明らかなものとして想定されているのでしょうか。