showInt :: Int -> String
showInt x = show x
上記のコードは辞書show
を渡すことを呼び出しますか、それともインスタンスで宣言された関数を直接呼び出しますか?Int
Show Int
つまり、GHCは、可能であれば、生成されたコードから多形間接参照を削除しますか?
showInt :: Int -> String
showInt x = show x
上記のコードは辞書show
を渡すことを呼び出しますか、それともインスタンスで宣言された関数を直接呼び出しますか?Int
Show Int
つまり、GHCは、可能であれば、生成されたコードから多形間接参照を削除しますか?
はい。これは、GHC7.4.2を使用して生成されたコアです。
Foo.showInt :: GHC.Types.Int -> GHC.Base.String
[... attributes omitted ...]
Foo.showInt = GHC.Show.$fShowInt_$cshow
ご覧のとおり、これは。への直接参照にすぎませんGHC.Show.$fShowInt_$cshow
。
型シグネチャを削除して、推論された型Show a => a -> String
が代わりに使用される場合に何が起こるかを比較してください。
Foo.showInt
:: forall a_aop. GHC.Show.Show a_aop => a_aop -> GHC.Base.String
[... attributes omitted ...]
Foo.showInt =
\ (@ a_aot) ($dShow_aou :: GHC.Show.Show a_aot) (x_a9Z :: a_aot) ->
GHC.Show.show @ a_aot $dShow_aou x_a9Z
ここでは、ディクショナリ引数$dShow_aou
を取り、アクセサ関数を使用してGHC.Show.show
、結果の関数を引数に適用する前に、このディクショナリから適切な関数を検索しますx_a9Z
。
最初のケースで起こることは、少なくとも概念的には、具体的なタイプがわかっているため、GHCは引数としてではなく、適切なインスタンスディクショナリへの直接参照を挿入することです。次に、基本的に単なるレコードレーベルであるアクセサをインライン化して、適切な関数への直接参照を残すことができます。
GHCはそれを行いません。読みやすくするために新しく作成されたタイプを考えてみてください。
type Vector = (Float, Float)
GHCが次のような関数から多形性を削除する場合:
(!+!) :: Vector -> Vector -> Vector
(x1, y1) !+! (x2, y2) = (x1 + x2, y1 + y2)
タイプは次のようになります。
(!+!) :: (Float, Float) -> (Float, Float) -> (Float, Float)
関数は特にVector用ですが。