あなたのコメントは、それ自体ではなく、の内容をシリアライズしたいという意味だと理解しました。TVar
TVar
から値を抽出する方法は 1 つしかありません。TVar
それは次のreadTVar
とおりです。
readTVar :: TVar a -> STM a
IO
...を使用してモナドで行うことができますatomically
:
atomically . readTVar :: TVar a -> IO a
TChan
ただし、全体をフラッシュしないと内容を検査できないため、より注意が必要ですTChan
。STM
これは、内容全体を 1 回のアクションとして検査し、それらをすべて再挿入することによって、たとえ無駄があったとしても実行可能です。これを選択した場合、最終的にはIO
モナドで実行する必要があります。
これは、モナドに存在するものではなく、それを に変換する純粋な計算を期待するShow
ため、そのインスタンスを派生させることができないことを意味します。Show
String
IO
Show
ただし、クラスを使用しなければならない理由はありません。IO
カスタム関数を定義して、モナドでデータ型をシリアル化できます。Show
また、次の理由から、シリアル化の目的で使用することは一般的にお勧めできません。
- 一部のデータ型 ( など
PSQ
) にはRead
インスタンスがありません
Read
一般的にインスタンスを定義するのは面倒です
- 文字列表現は非常にスペース効率が悪い
binary
そのため、シリアライゼーションとデシリアライゼーションを行うために、またはのような適切なシリアライゼーション ライブラリを使用することをお勧めしますcereal
。これらはデータ型をバイナリ表現に変換し、エンコーダーとデコーダーの定義を非常に簡単にします。
ただし、これらのライブラリでさえ、純粋な変換のインスタンスのみを受け入れ、IO
モナドでの操作は受け入れないため、シリアライゼーションを 2 段階のプロセスに分解する必要があります。
- モナド
TVar
で s の内容を抽出します。IO
cereal
/を使用してコンテンツを (残りのデータ型と共に) シリアル化しますbinary
。
すべてのデータ型にインスタンスがあるわけではありません(パッケージBinary
を使用すると仮定します) が、幸いにもリストにはインスタンスがあるため、便利な回避策は、データ型をリストに変換することです。 (リストを使用してシリアル化します。次に、リストを逆シリアル化するときに、を使用して元の型を復元します。binary
Binary
toList
fromList
したがって、次の関数はそのすべてを行います ( を使用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
パッケージの使用方法を学習すれば、十分に簡単に理解できるはずです。