あなたのコメントは、それ自体ではなく、の内容をシリアライズしたいという意味だと理解しました。TVarTVar
から値を抽出する方法は 1 つしかありません。TVarそれは次のreadTVarとおりです。
readTVar :: TVar a -> STM a
IO...を使用してモナドで行うことができますatomically:
atomically . readTVar :: TVar a -> IO a
TChanただし、全体をフラッシュしないと内容を検査できないため、より注意が必要ですTChan。STMこれは、内容全体を 1 回のアクションとして検査し、それらをすべて再挿入することによって、たとえ無駄があったとしても実行可能です。これを選択した場合、最終的にはIOモナドで実行する必要があります。
これは、モナドに存在するものではなく、それを に変換する純粋な計算を期待するShowため、そのインスタンスを派生させることができないことを意味します。ShowStringIO
Showただし、クラスを使用しなければならない理由はありません。IOカスタム関数を定義して、モナドでデータ型をシリアル化できます。Showまた、次の理由から、シリアル化の目的で使用することは一般的にお勧めできません。
- 一部のデータ型 ( など
PSQ) にはReadインスタンスがありません
Read一般的にインスタンスを定義するのは面倒です
- 文字列表現は非常にスペース効率が悪い
binaryそのため、シリアライゼーションとデシリアライゼーションを行うために、またはのような適切なシリアライゼーション ライブラリを使用することをお勧めしますcereal。これらはデータ型をバイナリ表現に変換し、エンコーダーとデコーダーの定義を非常に簡単にします。
ただし、これらのライブラリでさえ、純粋な変換のインスタンスのみを受け入れ、IOモナドでの操作は受け入れないため、シリアライゼーションを 2 段階のプロセスに分解する必要があります。
- モナド
TVarで s の内容を抽出します。IO
cereal/を使用してコンテンツを (残りのデータ型と共に) シリアル化しますbinary。
すべてのデータ型にインスタンスがあるわけではありません(パッケージBinaryを使用すると仮定します) が、幸いにもリストにはインスタンスがあるため、便利な回避策は、データ型をリストに変換することです。 (リストを使用してシリアル化します。次に、リストを逆シリアル化するときに、を使用して元の型を復元します。binaryBinarytoListfromList
したがって、次の関数はそのすべてを行います ( を使用binary):
serializeQcfg file (Qcfg qthresh tdelay cwpsq cwmap cwchan) = do
-- Step 1: Extract contents of concurrency variables
psq <- atomically $ readTVar cwpsq
myMap <- atomically $ readTVar cwmap
myChan <- atomically $ entireTChan cwchan
-- Step 2: Encode the extracted data
encodeFile file (qthresh, tdelay, toList psq, myMap, myChan)
編集:実際には、ダニエルが指摘したように、すべてのアトミックトランザクションを単一のトランザクションに結合する方がおそらく良いので、実際には次のようにします。
serializeQcfg file (Qcfg qthresh tdelay cwpsq cwmap cwchan) = do
-- Step 1: Extract contents of concurrency variables
(psq, myMap, myChain) <- atomically $ (,,) <$> readTVar cwpsq
<*> readTVar cwmap
<*> entireTChan cwchan
-- Step 2: Encode the extracted data
encodeFile file (qthresh, tdelay, toList psq, myMap, myChan)
entireTChan基本的に をフラッシュしTChanてコンテンツ全体を検査してから再度リロードするの実装を省略しましたが、その型シグネチャは次のようになります。
entireTChan :: TChan a -> STM [a]
デシリアライゼーションの実装も省略しましたが、上記の例を理解し、時間をかけてbinaryまたはcerealパッケージの使用方法を学習すれば、十分に簡単に理解できるはずです。