2013-06-17 24 views
7

今日、タイプシグネチャタイプのデータを格納しないようにデータタイプを構築することが可能かどうかを調べたいと思っていましたが、 。ですから、ここにはタイプコンストラクタがaであるが、タイプがByteStringのデータコンストラクタを持つGADTの試みがあります。タイプ制約を持つGADTのFunctorインスタンス

{-# LANGUAGE GADTs #-} 
import Data.ByteString.Char8 
import Data.Serialize 

data Serialized a where 
    MkSerialized :: (Serialize a) => ByteString -> Serialized a 

今、私は次のようにdecode'関数を定義することができます

decode' :: (Serialize a) => Serialized a -> a 
decode' (MkSerialized bs) = let Right r = (decode bs) in r 

そして、それは動作します:

let s = MkSerialized (encode "test") :: Serialized String 
print $ decode' s  -- prints "test" 

私の問題は、私はSerializedがなりたいということになりましたFunctorのインスタンス。

しかし、私はエラー(Serialize b)を推測できません。 Functorインスタンスを制約して、Serializefmapに適用されるようにするにはどうすればよいですか?

+2

できません。 'Functor'では、型パラメータの制約が必要になります。 'rmonad'パッケージ(http://hackage.haskell.org/packages/archive/rmonad/0.8/doc/html/Control-RMonad.html#t:RFunctor)には、制限されたファンクタクラス[' RFunctor']があります。多分あなたはそれを使うことができます。 –

+2

これはあなたの質問には関係ありません。これは 'Functor'では実際には不可能ですが、私は言及する義務があります。デフォルトで' Data.ByteString.Char8'を使用しないでください!これは壊れたコードを奨励する壊れたモジュールです。時にはいくつかの用途がありますが、あなたのコードはUnicodeの誤解を招かない 'Data.ByteString'でも同様に動作します。 – shachaf

+1

これは価値があると思いますが、ByteString - >(x - > a) - > Serialized a'のような 'Coordinated'スタイルのデータ型を' MkSerialized :: Serialize x =>ポスト・デシリアライゼーション機能を持ち、 'Functor'インスタンスを持っています。もちろん、それはここの目的を破るものです。 – shachaf

答えて

6

CoYonedaファンクタを使用してこれを行うことができます。

アイデアは単純です:機能を蓄積するための追加の機能フィールドがあります。fmap機能を追加してください。あなたの価値をデコードするときは、その関数を適用します。あなたのケースになりますよう、

{-# LANGUAGE GADTs #-} 
import Data.ByteString.Char8 
import Data.Serialize 

data Serialized a where 
    MkSerialized 
     :: (Serialize a) 
     => ByteString -> (a -> b) -> Serialized b 

decode' :: Serialized a -> a 
decode' (MkSerialized bs f) = let Right r = decode bs in f r 

instance Functor Serialized where 
    fmap f (MkSerialized bs g) = MkSerialized bs (f . g) 

また、これは自動的に複数のfmapの代わりに繰り返しデコーディングとエンコーディングを融合する利点を有する:

は、ここでは、コードです。

+2

これは実際に私の問題を解決しているわけではありませんが(私は 'fmap'が繰り返しデコード/エンコードを行うのが好きだったので)、私はこの答えを受け入れますか?私は私の元のアイデアは不可能であると見ています。制約のあるGADTのファンクタを定義する最も実用的な方法です。また、[GADTと米田ファンクタのための興味深い読書](http://www.haskellforall.com/2012/06/gadts.html)。 – Phae7rae

関連する問題