事実上の標準Haskellコンパイラの新しいバージョン-GHC 8.2.1! このリリースは反復的な改良ですが、同時に、コードの記述の利便性、表現力のある言語、コンパイルされたプログラムのパフォーマンスに関連する興味深い新機能も多数備えています。 私の意見では、最も興味深い変更について考えてみましょう!
コンパクトな地域
パフォーマンスに直接影響する変更の1つです。 特定のデータセットを1つの大きなオブジェクト(領域)としてマークし、ガベージコレクター(コンパクト)を1回実行し、この領域内に少なくとも1つのリンクがある限り、内部に登ってオブジェクトグラフに沿って実行しないで生きていると見なすことができます後続のアセンブリで。
これは、たとえば、作業の最初の段階でプログラムが大きなデータセットを作成し、その後のほとんどの期間で使用する場合に役立ちます。 たとえば、
公式の説明では、例としてガベージコレクション時間が1.5倍のスペルチェッカーの辞書を挙げており、一部のテストではGCに費やされる時間が2〜3倍短縮されています。 正式なロジックと実装の説明を
書いた紙張りの人は(おそらく若干より総合的なベンチマークで)いくつかのクレイジーな数値(p。9、チャート7〜8)を導きます。ここで、ゲインは時々桁違いであり、Haskell GCはそのような生産準備を追い越し始めます-GCが隠されたOracle JVMのようなモンスター。
これを使用するのは非常に簡単です。特定の値から領域を作成するには、
Data.Compact
モジュールの関数
compact :: a -> IO (Compact a)
Data.Compact
compact :: a -> IO (Compact a)
を
Data.Compact
ます。その後、
getCompact :: Compact a -> a
。 合計すると、次のようになります。
compacted <- getCompact <$> compact someBigHeavyData
当然、コンパクトな領域を作成する場合、オブジェクトはほぼ完全に計算されます(より具体的には、領域が閉じていることを証明するのに十分です)。したがって、たとえば、無限リストを圧縮することはお勧めできません。
さらに、結果のコンパクト領域をシリアル化および逆シリアル化できます。 確かに、予約あり:シリアル化解除プログラムは、一般に、アドレス空間まで、シリアル化プログラムとまったく同じである必要があります。そのため、ASLRでさえすべてを壊します。
フランクリンへのちょっとした言及上記の記事を注意深く読むと、compactclass compactable aが記事に追加され、 compact
関数のシグネチャがCompactable a => a -> IO (Compact a)
ます。 実際のAPIでは、この定数は存在せず、関数のドキュメントのエントリには、領域などに可変データがある場合、互換性のないコアが例外をスローすることが記載されています。 したがって、この場合、著者は使いやすさのためにタイプセーフを犠牲にしているようです。
導出戦略
GHCには、クラスのインスタンスクラスを推測するための少なくとも3つ半のメカニズムがあります。
1.標準クラス(
Show
、
Read
、
Eq
)およびGHCがそれ自体を出力できるクラス(すべての種類の
Functor
および
Traversable
、ならびに
Data
、
Typeable
および
Generic
)の出力。
2.
DeriveAnyClass
拡張により有効化されたデフォルトのメソッド実装を介した出力
例この場合、発表
{-# LANGUAGE DeriveAnyClass #-} class Foo a where doFoo :: a -> b doFoo = defaultImplementation data Bar = Bar deriving(Foo)
で行われます
data Bar = Bar instance Foo Bar
Foo
がGenericsメカニズム(たとえば、
Aesonによる JSONや
CassavaによるCSVへの変換のインスタンスなど)を通じて表示できる場合、または
Foo
の最小限の定義がメソッドをまったく必要
Foo
ない場合(よりアカデミックな記述を作成する場合に便利)タイムクラスが定理の条件の証人として使用される場合のコード)。
3.
newtype
を介して作成された型のエイリアスの場合、
GeneralizedNewtypeDeriving
拡張機能を介してベース型のtypclassesの実装を直接使用することもできます。
{-# LANGUAGE GeneralizedNewtypeDeriving #-} newtype WrappedInt = WrappedInt { unwrap :: Int } deriving(Unbox)
したがって、問題は、GHC 8.2より前では、複数の拡張機能を一度に有効にするとどのメカニズムを使用するかを指定することができなかったことです-たとえば、
DeriveAnyClass
と
GeneralizedNewtypeDeriving
同時に有効にすると、最初の拡張が優先されます。実際、同じモジュールで両方の拡張機能を使用できませんでした。
今、あなたは書くことができます
{-# LANGUAGE DeriveAnyClass, GeneralizedNewtypeDeriving, DerivingStrategies #-} newtype Baz = Baz Quux deriving (Eq, Ord) deriving stock (Read, Show) deriving newtype (Num, Floating) deriving anyclass C
スタンドアロンの派生宣言で戦略を指定できます。
data Foo = Foo deriving anyclass instance C Foo
興味深いことに、以前のバージョンでは
{-# #-}
を使用することが提案されていましたが、最終的には上記のアプローチが実装されました。
その他のインスタンスの自動拡張
DeriveAnyClass
賢明。 第一に、署名
*
または
* -> *
持つ時間クラスに制限されなくなりました。 次に、デフォルトの実装定数からインスタンス制約が導出されます。 そのため、たとえば、このようなコードはこれまでに追加されていません。
{-# LANGUAGE DeriveAnyClass, DefaultSignatures #-} class Foo a where bar :: a -> String default bar :: Show a => a -> String bar = show baz :: a -> a -> Bool default baz :: Ord a => a -> a -> Bool baz xy = compare xy == EQ data Option a = None | Some a deriving (Eq, Ord, Show, Foo)
Foo
のインスタンスには定数
(Ord a, Show a)
がなく、コンパイラーはそれらを手動で追加することを提案したためです。 これで、対応する定数が出力インスタンスに自動的に追加されます。
GeneralizedNewtypeDeriving
も考案されました。 場合によっては(実際、実際に興味深いもののほとんどで)、タイプクラスに関連付けられたタイプも自動的に表示されます。 例えば型の場合
class HasRing a where type Ring a newtype L1Norm a = L1Norm a deriving HasRing
コンパイラはインスタンスを生成します
instance HasRing (L1Norm a) where type Ring (L1Norm a) = Ring a
バックパック
現在、OCaml信者はHaskellistsをトロールする理由がわずかに少なくなっています:GHC 8.2は、以前よりもはるかに高度なモジュールシステムを導入しました-バックパック。 これ自体はかなり大きく複雑な変更であり、別の記事にふさわしいので、正式な説明と短い
例で 論文著者の
論文を参照します。
その他
選択した他の変更をリストします。
- コンパイラ自体の内部では、結合点の概念が形式化されています。つまり、この分岐の後に常に実行されるコードのブロックです。 これにより、コンパイルされたコードのパフォーマンスがわずかではあるが統計的に有意に向上し、さらなる最適化の可能性が広がります。
- NUMAシステムのパフォーマンスが向上しました。
- プログラム自体の
ミューテーターに直接割り当てるよりも少ない数のスレッドをガベージコレクターに割り当てる機能が追加されました。 この投稿では、Simon MarlowがFacebookでHaskellを使用するコンテキストでこれを実装する方法と理由を説明します。 - レビティポリモーフィズムのサポートの改善。これは、
*
住むタイプ(多かれ少なかれ私たちが愛する普通のタイプ)と#
住むタイプ(遅延ボックス化されていないタイプ)の両方で機能する関数を記述する責任があります。 - 反射の安全性の向上。
- 標準のldリンカーの代わりにld.goldまたはld.lldを使用する機能。
- エラーメッセージは、色付きで、clangスタイルのエラー位置ポインターで作成されるようになりました。