次のバージョンである GHC 8.0 では、正格評価用のプラグマして Strict と StrictData が提供されます。環境を作ってみたので、少し試しました。

以下のファイルを用意します。

{-# LANGUAGE DeriveFunctor #-} module A where data List a = Nil | Cons a (List a) deriving (Eq,Functor) xs :: List Int xs = Cons 1 (Cons 2 Nil)

注意：

トップレベルの束縛とローカルの束縛では挙動が違います。Strict が効くのは、ローカルの束縛です。なので、GHCi で let を使って試します。

評価が遅延しているかは、GHCi の :sprint コマンドで確かめられます。GHC 7.8 以降の GHCi では MonomorphismRestriction が無効になっており、これが :sprint の動作に悪影響を与えますので、型が特定されるように型注釈を補うことを忘れないで下さい。(たとえば、上記 xs。)

いままで通り % ghci A.hs > let ys = (+1) xs > :sprint ys ys = _ > ys `seq` () () > :sprint ys ys = Cons _ _ 関数適用も遅延するし、評価してもリストの構造が遅延していることが分かります。

StrictData % ghci -XStrictData A.hs > let ys = (+1) xs > :sprint ys ys = _ > ys `seq` () () > :sprint ys ys = Cons 2 (Cons 3 Nil) リスト構造の遅延がなくなり、正格データとなりました。つまり、以下と同じ扱いです。 data List a = Nil | Cons ! a ! (List a) deriving (Eq,Functor)

Strict % ghci -XStrict A.hs > let ys = (+1) xs > :sprint ys ys = Cons _ _ > ys `seq` () () > :sprint ys ys = Cons _ _ ローカルの変数束縛は遅延していません。リストの構造は遅延しています。つまり、以下のように BangPatterns で書くのと同じです。 > let !ys = (+1) xs

StrictData & Strict % ghci -XStrictData -XStrict A.hs > let ys = (+1) xs > :sprint ys ys = Cons 2 (Cons 3 Nil) あー、もう、正格評価の言語みたい。:-) Haskell で正格評価のプログラミングをしたければ、こんな感じになります。 {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE Strict #-} {-# LANGUAGE StrictData #-} module A where data List a = Nil | Cons a (List a) deriving (Eq,Functor) xs :: List Int xs = Cons 1 (Cons 2 Nil)