为什么我使用GHC.Generics得到一个模糊的类型变量错误?

时间:2012-10-23 18:02:45

标签: generics haskell ghc

我试过这个例子 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

这里缺少什么?

1 个答案:

答案 0 :(得分:2)

问题是因为a中的类型变量UserTree aLeaf构造函数中根本没有出现,所以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)