考虑下面的自由么半群的类型类。
class FreeMonoid f where
inj :: a -> f a
univ :: Monoid m => (a -> m) -> f a -> m
inj
向自由幺半群注入一个值,并且univ
是自由幺半群的泛性质。
此类的示例应满足以下规则。
*身份:univ f . inj = f
*自由空:univ f mempty = mempty
*自由追加:univ f (m <> n) = univ f m <> univ f n
注意,如果f
是FreeMonoid
的一个示例,那么(f a)
必须是Monoid
的一个示例,否则,最后两个定律就没有意义了,那么,我如何指定这个约束呢?
class Monoid (f a) => FreeMonoid f where
inj :: a -> f a
univ :: Monoid m => (a -> m) -> f a -> m
没有这个约束会使使用这个类变得不方便。例如,考虑下面的函数。
mapFreeMonoid :: (FreeMonoid f, Monoid (f b)) => (a -> b) -> f a -> f b
mapFreeMonoid f = univ (inj . f)
由于f
是FreeMonoid
的一个示例,我们不需要指定Monoid (f b)
约束,理想情况下,我们应该能够如下定义上述函数。
mapFreeMonoid :: FreeMonoid f => (a -> b) -> f a -> f b
mapFreeMonoid f = univ (inj . f)
2条答案
按热度按时间x4shl7ld1#
您可以尝试使用
QuantifiedConstraints
扩展。然后,您的代码将在没有附加约束的情况下进行编译。
vnjpjtjt2#
你可以像chi回答的那样使用QuantifiedConstraints扩展,看看自由范畴的类似定义,这里是CFree约束。