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

问题是,由于类型变量ainUserTree 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 回答