根据我之前收到的建议(How to write an instance for Generic to derive a function like zero::a (i.e. a constant)?)我成功添加了类似的函数,但是失败的函数转换了一个用类型包装的值中的单个值(例如singleton :: a - &gt ; [一个])。
我到目前为止:
class Single l where
mkOne :: x -> l
default mkOne :: (Generic l, Generic x, Single l, Gsingle (Rep l)) => x -> l
mkOne x = to ( gmkOne (from x))
class Gsingle l where
gmkOne :: x -> l x
instance Gsingle U1 where -- this is for zero
gmkOne x = U1
instance (Gsingle a) => Gsingle (K1 i a) where
gmkOne (K1 x) = K1 (mkOne x)
instance Single f => Gsingle (M1 i c f) where
gmkOne (M1 x1) = M1 (gmkOne x1)
instance (Gsingle f, Gsingle h) => Gsingle (f :*: h) where
gmkOne (x1 :*: y1) = gmkOne x1:*: gmkOne y1
通过查看我不理解x
中的Gsingle
类型参数的示例,或者更确切地说如何处理Gsingle中的签名x -> lx
,我的印象很明显。
我尝试使用类型系列:
class Single l where
type ST l
mkOne :: (ST l) -> l
default mkOne :: (Generic l, Generic (ST l), Single l, Gsingle (Rep l)) => (ST l) -> l
mkOne x = to ( gmkOne (from x))
class Gsingle l where
type STG l
gmkOne :: (STG l) -> l x
instance Gsingle U1 where -- this is for zero
gmkOne x = U1
instance (Gsingle a) => Gsingle (K1 i a) where
gmkOne (K1 x) = K1 (mkOne x)
instance Single f => Gsingle (M1 i c f) where
gmkOne (M1 x1) = M1 (gmkOne x1)
instance (Gsingle f, Gsingle h) => Gsingle (f :*: h) where
gmkOne (x1 :*: y1) = gmkOne x1:*: gmkOne y1
但实例Gsingle (M1 i c f)
和Gsingle (f :*: h)
中的类型错误仍然存在。
答案 0 :(得分:2)
这个类通常被称为“尖头”,可以表示为:
class Pointed f where
point :: a -> f a
default point :: (Generic1 f, Pointed (Rep1 f)) => a -> f a
point = to1 . point
您只需要每个构造函数的实例:
instance Pointed c => Pointed (M1 i t c) where
point = M1 . point
instance Monoid c => Pointed (K1 i c) where
point _ = K1 mempty
instance Pointed U1 where
point _ = U1
instance Pointed r => Pointed (l :+: r) where
point = R1 . point
instance (Pointed l, Pointed r) => Pointed (l :*: r) where
point x = point x :*: point x
instance Pointed Par1 where
point = Par1
instance Pointed f => Pointed (Rec1 f) where
point = Rec1 . point
instance (Pointed l, Pointed r) => Pointed (l :.: r) where
point = Comp1 . point . point
然后它会正常工作:
data Three a = Three a a a deriving (Show,Generic1)
>>> point True :: Three Bool
Three True True True
instance Pointed []
>>> point True :: [Bool]
[True,True,True,True,True,True...
您可能会注意到pure
类中与Applicative
的相似性:GHC库邮件列表上实际上有a proposal,以便将此精确实例添加到上面的每个构造函数中。