2

http://www.haskell.org/haskellwiki/GHC.Generics#A_generic_functionの例を試しました

あれは:

import GHC.Generics

{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DefaultSignaturesGeneric #-}

data Bin = O | I deriving Show

data UserTree a = Node a (UserTree a) (UserTree a) | Leaf deriving Generic

class GSerialize f where
    gput :: f a -> [Bin]

instance GSerialize U1 where
    gput U1 = []

instance (GSerialize a, GSerialize b) => GSerialize (a :*: b) where
    gput (x :*: y) = gput x ++ gput y

instance (GSerialize a, GSerialize b) => GSerialize (a :+: b) where
    gput (L1 x) = O : gput x
    gput (R1 x) = I : gput x

instance (GSerialize a) => GSerialize (M1 i c a) where
    gput (M1 x) = gput x

instance (Serialize a) => GSerialize (K1 i a) where
    gput (K1 x) = put x

class Serialize a where
    put :: a -> [Bin]
    default put :: (Generic a, GSerialize (Rep a)) => a -> [Bin]
    put = gput . from

instance Serialize Int
instance Serialize Char
instance Serialize Bool
instance (Serialize a) => Serialize (UserTree a)

toserialize :: (Serialize (UserTree a) ) => UserTree a -> [Bin]
toserialize tree = put tree

次の呼び出しで関数をテストしました。

toserialize Leaf

ここで、コンパイラはエラー メッセージを表示します。

 Ambiguous type variable `a0' in the constraint:
   (Serialize a0) arising from a use of `toserialize'
 Probable fix: add a type signature that fixes these type variable(s)
 In the expression: serialize Leaf
 In an equation for `it': it = toserialize Leaf

ここに何が欠けていますか?

4

1 に答える 1

2

a問題は、 inの型変数がコンストラクターUserTree aにまったく表示されLeafないため、GHC がa値に必要なものを判断できないことです。次のような明示的な型シグネチャを追加することで、これを修正できます。

toserialize (Leaf :: UserTree Int)

更新: の一般的な表現が再帰的toserialize (Node 2 Leaf Leaf)であるため、例がハングしますInt

type Rep Int = D1 D_Int (C1 C_Int (S1 NoSelector (Rec0 Int)))

「通常の」コンストラクターを持たない「プリミティブ」型の場合、通常は手動でインスタンスを定義する必要があります。ただし、たとえばBool単純に

data Bool = True | False

これはジェネリックSerializeインスタンスで動作します

toserialize (Node True Leaf Leaf)
于 2012-10-23T18:23:08.440 に答える